diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py index 84b3a84514..248e873cdd 100644 --- a/ci-scripts/args_parse.py +++ b/ci-scripts/args_parse.py @@ -41,7 +41,7 @@ import constants as CONST #----------------------------------------------------------- -def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): +def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP): py_param_file_present = False @@ -79,6 +79,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): RAN.ranRepository=matchReg.group(1) HTML.ranRepository=matchReg.group(1) ldpc.ranRepository=matchReg.group(1) + CONTAINERS.ranRepository=matchReg.group(1) elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) @@ -90,6 +91,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): CiTestObj.ranAllowMerge = True RAN.ranAllowMerge=True HTML.ranAllowMerge=True + CONTAINERS.ranAllowMerge=True elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) @@ -99,6 +101,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): RAN.ranBranch=matchReg.group(1) HTML.ranBranch=matchReg.group(1) ldpc.ranBranch=matchReg.group(1) + CONTAINERS.ranBranch=matchReg.group(1) elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) @@ -108,6 +111,7 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): RAN.ranCommitID=matchReg.group(1) HTML.ranCommitID=matchReg.group(1) ldpc.ranCommitID=matchReg.group(1) + CONTAINERS.ranCommitID=matchReg.group(1) elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) @@ -117,50 +121,63 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): RAN.ranTargetBranch=matchReg.group(1) HTML.ranTargetBranch=matchReg.group(1) ldpc.ranTargetBranch=matchReg.group(1) + CONTAINERS.ranTargetBranch=matchReg.group(1) elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNBIPAddress=matchReg.group(1) ldpc.eNBIpAddr=matchReg.group(1) + CONTAINERS.eNBIPAddress=matchReg.group(1) elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1IPAddress=matchReg.group(1) + CONTAINERS.eNB1IPAddress=matchReg.group(1) elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) RAN.eNB2IPAddress=matchReg.group(1) + CONTAINERS.eNB2IPAddress=matchReg.group(1) elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) RAN.eNBUserName=matchReg.group(1) ldpc.eNBUserName=matchReg.group(1) + CONTAINERS.eNBUserName=matchReg.group(1) elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1UserName=matchReg.group(1) + CONTAINERS.eNB1UserName=matchReg.group(1) elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) RAN.eNB2UserName=matchReg.group(1) + CONTAINERS.eNB2UserName=matchReg.group(1) elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) RAN.eNBPassword=matchReg.group(1) ldpc.eNBPassWord=matchReg.group(1) + CONTAINERS.eNBPassword=matchReg.group(1) elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1Password=matchReg.group(1) + CONTAINERS.eNB1Password=matchReg.group(1) elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) RAN.eNB2Password=matchReg.group(1) + CONTAINERS.eNB2Password=matchReg.group(1) elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) RAN.eNBSourceCodePath=matchReg.group(1) ldpc.eNBSourceCodePath=matchReg.group(1) + CONTAINERS.eNBSourceCodePath=matchReg.group(1) elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) RAN.eNB1SourceCodePath=matchReg.group(1) + CONTAINERS.eNB1SourceCodePath=matchReg.group(1) elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) RAN.eNB2SourceCodePath=matchReg.group(1) + CONTAINERS.eNB2SourceCodePath=matchReg.group(1) elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) EPC.IPAddress=matchReg.group(1) diff --git a/ci-scripts/build_fr1_from_yaml.py b/ci-scripts/build_fr1_from_yaml.py new file mode 100755 index 0000000000..a5492df6f6 --- /dev/null +++ b/ci-scripts/build_fr1_from_yaml.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Jul 7 23:04:51 2020 + +@author: hardy +""" + + + +import yaml +import sys +import subprocess + + + +def main(): + f_yaml=sys.argv[1] + f_sh=sys.argv[2] + #filename='py_params_template.yaml' + with open(f_yaml,'r') as file: + # The FullLoader parameter handles the conversion from YAML + # scalar values to Python the dictionary format + print('Loading '+f_yaml) + params = yaml.load(file,Loader=yaml.FullLoader) + + + with open(f_sh,'w') as f: + f.write('#!/bin/sh\n') + for i in range (0, len(params['steps'])): + step=params['steps'][i].split(',') + mode=step[0] + f_xml=step[1] + line='python3 main.py ' + \ + '--mode='+ mode + ' ' + \ + '--ranRepository=' + params['ranRepository'] + ' ' + \ + '--ranBranch=' + params['ranBranch'] + ' ' + \ + '--ranCommitID=' + params['ranCommitID'] + ' ' + \ + '--ranAllowMerge=' + params['ranAllowMerge'] + ' ' + \ + '--ranTargetBranch=' + params['ranTargetBranch'] + ' ' + \ + \ + '--ADBIPAddress=' + params['ADB']['ADBIPAddress'] + ' ' + \ + '--ADBUserName=' + params['ADB']['ADBUserName'] + ' ' + \ + '--ADBPassword=' + params['ADB']['ADBPassword'] + ' ' + \ + \ + '--UEIPAddress=' + params['UE']['UEIPAddress'] + ' ' + \ + '--UEUserName=' + params['UE']['UEUserName'] + ' ' + \ + '--UEPassword=' + params['UE']['UEPassword'] + ' ' + \ + '--UESourceCodePath=' + params['UE']['UESourceCodePath'] + ' ' + \ + \ + '--EPCIPAddress=' + params['EPC']['EPCIPAddress'] + ' ' + \ + '--EPCUserName=' + params['EPC']['EPCUserName'] + ' ' + \ + '--EPCPassword=' + params['EPC']['EPCPassword'] + ' ' + \ + '--EPCSourceCodePath=' + params['EPC']['EPCSourceCodePath'] + ' ' + \ + '--EPCType=' + params['EPC']['EPCType'] + ' ' + \ + \ + '--eNBIPAddress=' + params['RAN'][0]['eNBIPAddress'] + ' ' + \ + '--eNBUserName=' + params['RAN'][0]['eNBUserName'] + ' ' + \ + '--eNBPassword=' + params['RAN'][0]['eNBPassword'] + ' ' + \ + '--eNBSourceCodePath=' + params['RAN'][0]['eNBSourceCodePath'] + ' ' + \ + \ + '--eNB1IPAddress=' + params['RAN'][1]['eNB1IPAddress'] + ' ' + \ + '--eNB1UserName=' + params['RAN'][1]['eNB1UserName'] + ' ' + \ + '--eNB1Password=' + params['RAN'][1]['eNB1Password'] + ' ' + \ + '--eNB1SourceCodePath=' + params['RAN'][1]['eNB1SourceCodePath'] + ' ' + if mode!="InitiateHtml": + line+='--XMLTestFile=' + f_xml + #if mode is InitiateHTML we have a special processing to mention all xml files from the list + #loop starting at 1 to avoid the xml file mentioned with InitiateHtml in yaml file (file is none) + else: + for i in range (1, len(params['steps'])): + step=params['steps'][i].split(',') + f_xml=step[1] + line+='--XMLTestFile=' + f_xml+' ' + line+='\n' + print(line) + f.write(line) + subprocess.call(['chmod','777',f_sh]) + +if __name__ == "__main__": + main() + + diff --git a/ci-scripts/build_fr1_template.yaml b/ci-scripts/build_fr1_template.yaml new file mode 100755 index 0000000000..2a8f9cc6a0 --- /dev/null +++ b/ci-scripts/build_fr1_template.yaml @@ -0,0 +1,46 @@ + +ranRepository : https://gitlab.eurecom.fr/oai/openairinterface5g.git +ranBranch : BRANCH_NAME +ranCommitID : COMMIT_ID +ranAllowMerge : 'true' +ranTargetBranch : develop + +steps: + - InitiateHtml,none + - TesteNB,xml_files/fr1_multi_node_build.xml + - TesteNB,xml_files/fr1_epc_start.xml + - TesteNB,xml_files/fr1_ran_ue_base.xml #ue toggle, nodes initialize, ue toggle, ping, nodes terminate + - TesteNB,xml_files/fr1_epc_closure.xml + + +ADB: #on Caracal + ADBIPAddress : 192.168.18.196 + ADBUserName : oaici + ADBPassword : KkexF6CErOi1fNuebCPsuIVK + +RAN: + - eNBIPAddress : 192.168.18.199 #eNB on Minimassive + eNBUserName : oaicicd + eNBPassword : HzB*nkryaITdVd08TKlT#2Z5a!7M#~qn + eNBSourceCodePath : /tmp/CI-FR1-eNB + - eNB1IPAddress : 192.168.18.198 #gNB on Mozart + eNB1UserName : oaicicd + eNB1Password : 7zkDOFgh@w3HvRBMPTMh@BAx + eNB1SourceCodePath : /tmp/CI-FR1-gNB + + +EPC: #on Nikaia + EPCIPAddress : 192.168.18.99 + EPCUserName : nikaia + EPCPassword : linux + EPCSourceCodePath : /tmp/CI-FR1-EPC + EPCType : ltebox + + +UE: + UEIPAddress : none + UEUserName : none + UEPassword : none + UESourceCodePath : none + + diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py new file mode 100644 index 0000000000..1f95d2602f --- /dev/null +++ b/ci-scripts/cls_containerize.py @@ -0,0 +1,410 @@ +#/* +# * 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 +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import logging +import os +import time +from multiprocessing import Process, Lock, SimpleQueue + +#----------------------------------------------------------- +# OAI Testing modules +#----------------------------------------------------------- +import sshconnection as SSH +import helpreadme as HELP +import constants as CONST + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class Containerize(): + + def __init__(self): + + self.ranRepository = '' + self.ranBranch = '' + self.ranAllowMerge = False + self.ranCommitID = '' + self.ranTargetBranch = '' + self.eNBIPAddress = '' + self.eNBUserName = '' + self.eNBPassword = '' + self.eNBSourceCodePath = '' + self.eNB1IPAddress = '' + self.eNB1UserName = '' + self.eNB1Password = '' + self.eNB1SourceCodePath = '' + self.eNB2IPAddress = '' + self.eNB2UserName = '' + self.eNB2Password = '' + self.eNB2SourceCodePath = '' + self.forcedWorkspaceCleanup = False + self.imageKind = '' + self.eNB_instance = 0 + self.eNB_serverId = ['', '', ''] + self.yamlPath = ['', '', ''] + self.eNB_logFile = ['', '', ''] + + self.testCase_id = '' + + self.flexranCtrlDeployed = False + self.flexranCtrlIpAddress = '' + +#----------------------------------------------------------- +# Container management functions +#----------------------------------------------------------- + + def BuildImage(self, HTML): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + if self.eNB_serverId[self.eNB_instance] == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('Building on server: ' + lIpAddr) + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + + imageNames = [] + result = re.search('eNB', self.imageKind) + # Creating a tupple with the imageName and the DockerFile prefix pattern + if result is not None: + imageNames.append(('oai-enb', 'eNB')) + else: + result = re.search('gNB', self.imageKind) + if result is not None: + imageNames.append(('oai-gnb', 'gNB')) + else: + result = re.search('all', self.imageKind) + if result is not None: + imageNames.append(('oai-enb', 'eNB')) + imageNames.append(('oai-gnb', 'gNB')) + imageNames.append(('oai-lte-ue', 'lteUE')) + imageNames.append(('oai-nr-ue', 'nrUE')) + if len(imageNames) == 0: + imageNames.append(('oai-enb', 'eNB')) + # Workaround for some servers, we need to erase completely the workspace + if self.forcedWorkspaceCleanup: + mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) + self.testCase_id = HTML.testCase_id + # on RedHat/CentOS .git extension is mandatory + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + if result is not None: + full_ran_repo_name = self.ranRepository + else: + full_ran_repo_name = self.ranRepository + '.git' + mySSH.command('mkdir -p ' + lSourcePath, '\$', 5) + mySSH.command('cd ' + lSourcePath, '\$', 5) + mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) + + mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + mySSH.command('mkdir -p cmake_targets/log', '\$', 5) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + imageTag = 'develop' + if (self.ranAllowMerge): + imageTag = 'ci-temp' + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + mySSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + mySSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + # Let's remove any previous run artifacts if still there + mySSH.command('docker image prune --force', '\$', 5) + mySSH.command('docker image rm ran-build:' + imageTag, '\$', 5) + for image,pattern in imageNames: + mySSH.command('docker image rm ' + image + ':' + imageTag, '\$', 5) + # Build the shared image + mySSH.command('docker build --target ran-build --tag ran-build:' + imageTag + ' --file docker/Dockerfile.ran.ubuntu18 --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > cmake_targets/log/ran-build.log 2>&1', '\$', 800) + # Build the target image(s) + previousImage='ran-build:' + imageTag + danglingShaOnes=[] + for image,pattern in imageNames: + # the archived Dockerfiles have "ran-build:latest" as base image + # we need to update them with proper tag + mySSH.command('sed -i -e "s#ran-build:latest#ran-build:' + imageTag + '#" docker/Dockerfile.' + pattern + '.ubuntu18', '\$', 5) + mySSH.command('docker build --target ' + image + ' --tag ' + image + ':' + imageTag + ' --file docker/Dockerfile.' + pattern + '.ubuntu18 . > cmake_targets/log/' + image + '.log 2>&1', '\$', 600) + # Retrieving the dangling image(s) for the log collection + mySSH.command('docker images --filter "dangling=true" --filter "since=' + previousImage + '" -q | sed -e "s#^#sha=#"', '\$', 5) + result = re.search('sha=(?P[a-zA-Z0-9\-\_]+)', mySSH.getBefore()) + if result is not None: + danglingShaOnes.append((image, result.group('imageShaOne'))) + previousImage=image + ':' + imageTag + + imageTag = 'ci-temp' + # First verify if images were properly created. + status = True + mySSH.command('docker image inspect --format=\'Size = {{.Size}} bytes\' ran-build:' + imageTag, '\$', 5) + if mySSH.getBefore().count('No such object') != 0: + logging.error('Could not build properly ran-build') + status = False + else: + result = re.search('Size = (?P[0-9\-]+) bytes', mySSH.getBefore()) + if result is not None: + imageSize = float(result.group('size')) + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ran-build size is ' + ('%.0f' % imageSize) + ' kbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ran-build size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + logging.debug('\u001B[1m ran-build size is ' + ('%.3f' % imageSize) + ' Gbytes\u001B[0m') + else: + logging.debug('ran-build size is unknown') + for image,pattern in imageNames: + mySSH.command('docker image inspect --format=\'Size = {{.Size}} bytes\' ' + image + ':' + imageTag, '\$', 5) + if mySSH.getBefore().count('No such object') != 0: + logging.error('Could not build properly ' + image) + status = False + else: + result = re.search('Size = (?P[0-9\-]+) bytes', mySSH.getBefore()) + if result is not None: + imageSize = float(result.group('size')) + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ' + image + ' size is ' + ('%.0f' % imageSize) + ' kbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + if imageSize < 1000: + logging.debug('\u001B[1m ' + image + ' size is ' + ('%.0f' % imageSize) + ' Mbytes\u001B[0m') + else: + imageSize = imageSize / 1000 + logging.debug('\u001B[1m ' + image + ' size is ' + ('%.3f' % imageSize) + ' Gbytes\u001B[0m') + else: + logging.debug('ran-build size is unknown') + if not status: + mySSH.close() + logging.error('\u001B[1m Building OAI Images Failed\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTabFooter(False) + sys.exit(1) + + # Recover build logs, for the moment only possible when build is successful + mySSH.command('docker create --name test ran-build:' + imageTag, '\$', 5) + mySSH.command('mkdir -p cmake_targets/log/ran-build', '\$', 5) + mySSH.command('docker cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/ran-build', '\$', 5) + mySSH.command('docker rm -f test', '\$', 5) + for image,shaone in danglingShaOnes: + mySSH.command('mkdir -p cmake_targets/log/' + image, '\$', 5) + mySSH.command('docker create --name test ' + shaone, '\$', 5) + mySSH.command('docker cp test:/oai-ran/cmake_targets/log/. cmake_targets/log/' + image, '\$', 5) + mySSH.command('docker rm -f test', '\$', 5) + mySSH.command('docker image prune --force', '\$', 5) + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + mySSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + mySSH.close() + + logging.info('\u001B[1m Building OAI Image(s) Pass\u001B[0m') + HTML.CreateHtmlTestRow(self.imageKind, 'OK', CONST.ALL_PROCESSES_OK) + + def DeployObject(self, HTML, EPC): + if self.eNB_serverId[self.eNB_instance] == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('\u001B[1m Deploying OAI Object on server: ' + lIpAddr + '\u001B[0m') + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + # Putting the CPUs in a good state, we do that only on a few servers + mySSH.command('hostname', '\$', 5) + result = re.search('obelix|asterix', mySSH.getBefore()) + if result is not None: + mySSH.command('if command -v cpupower &> /dev/null; then echo ' + lPassWord + ' | sudo -S cpupower idle-set -D 0; fi', '\$', 5) + time.sleep(5) + + mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) + mySSH.command('cp docker-compose.yml ci-docker-compose.yml', '\$', 5) + imageTag = 'develop' + if (self.ranAllowMerge): + imageTag = 'ci-temp' + mySSH.command('sed -i -e "s/image: oai-enb:latest/image: oai-enb:' + imageTag + '/" ci-docker-compose.yml', '\$', 2) + localMmeIpAddr = EPC.MmeIPAddress + mySSH.command('sed -i -e "s/CI_MME_IP_ADDR/' + localMmeIpAddr + '/" ci-docker-compose.yml', '\$', 2) + if self.flexranCtrlDeployed: + mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED:.*/FLEXRAN_ENABLED: "yes"/\' ci-docker-compose.yml', '\$', 2) + mySSH.command('sed -i -e "s/CI_FLEXRAN_CTL_IP_ADDR/' + self.flexranCtrlIpAddress + '/" ci-docker-compose.yml', '\$', 2) + else: + mySSH.command('sed -i -e "s/FLEXRAN_ENABLED:.*$/FLEXRAN_ENABLED: \"no\"/" ci-docker-compose.yml', '\$', 2) + mySSH.command('sed -i -e "s/CI_FLEXRAN_CTL_IP_ADDR/127.0.0.1/" ci-docker-compose.yml', '\$', 2) + # Currently support only one + mySSH.command('docker-compose --file ci-docker-compose.yml config --services | sed -e "s@^@service=@"', '\$', 2) + result = re.search('service=(?P[a-zA-Z0-9\_]+)', mySSH.getBefore()) + if result is not None: + svcName = result.group('svc_name') + mySSH.command('docker-compose --file ci-docker-compose.yml up -d ' + svcName, '\$', 2) + + # Checking Status + mySSH.command('docker-compose --file ci-docker-compose.yml config', '\$', 5) + result = re.search('container_name: (?P[a-zA-Z0-9\-\_]+)', mySSH.getBefore()) + unhealthyNb = 0 + healthyNb = 0 + startingNb = 0 + containerName = '' + if result is not None: + containerName = result.group('container_name') + time.sleep(5) + cnt = 0 + while (cnt < 3): + mySSH.command('docker inspect --format=\'{{.State.Health.Status}}\' ' + containerName, '\$', 5) + unhealthyNb = mySSH.getBefore().count('unhealthy') + healthyNb = mySSH.getBefore().count('healthy') - unhealthyNb + startingNb = mySSH.getBefore().count('starting') + if healthyNb == 1: + cnt = 10 + else: + time.sleep(10) + cnt += 1 + logging.debug(' -- ' + str(healthyNb) + ' healthy container(s)') + logging.debug(' -- ' + str(unhealthyNb) + ' unhealthy container(s)') + logging.debug(' -- ' + str(startingNb) + ' still starting container(s)') + + status = False + if healthyNb == 1: + cnt = 0 + while (cnt < 20): + mySSH.command('docker logs ' + containerName + ' | egrep --text --color=never -i "wait|sync|Starting"', '\$', 30) + result = re.search('got sync|Starting F1AP at CU', mySSH.getBefore()) + if result is None: + time.sleep(6) + cnt += 1 + else: + cnt = 100 + status = True + logging.info('\u001B[1m Deploying OAI object Pass\u001B[0m') + time.sleep(10) + mySSH.close() + + self.testCase_id = HTML.testCase_id + self.eNB_logFile[self.eNB_instance] = 'enb_' + self.testCase_id + '.log' + + if status: + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + else: + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) + + def UndeployObject(self, HTML, RAN): + logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m') + if self.eNB_serverId[self.eNB_instance] == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId[self.eNB_instance] == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + logging.debug('\u001B[1m Deploying OAI Object on server: ' + lIpAddr + '\u001B[0m') + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) + # Currently support only one + mySSH.command('docker-compose --file ci-docker-compose.yml config', '\$', 5) + result = re.search('container_name: (?P[a-zA-Z0-9\-\_]+)', mySSH.getBefore()) + if result is not None: + containerName = result.group('container_name') + mySSH.command('docker kill --signal INT ' + containerName, '\$', 30) + time.sleep(5) + mySSH.command('docker logs ' + containerName + ' > ' + lSourcePath + '/cmake_targets/' + self.eNB_logFile[self.eNB_instance], '\$', 30) + mySSH.command('docker rm -f ' + containerName, '\$', 30) + + # Putting the CPUs back in a idle state, we do that only on a few servers + mySSH.command('hostname', '\$', 5) + result = re.search('obelix|asterix', mySSH.getBefore()) + if result is not None: + mySSH.command('if command -v cpupower &> /dev/null; then echo ' + lPassWord + ' | sudo -S cpupower idle-set -E; fi', '\$', 5) + mySSH.close() + + # Analyzing log file! + copyin_res = mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + self.eNB_logFile[self.eNB_instance], '.') + nodeB_prefix = 'e' + if (copyin_res == -1): + HTML.htmleNBFailureMsg='Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + else: + logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + self.eNB_logFile[self.eNB_instance]) + logStatus = RAN.AnalyzeLogFile_eNB(self.eNB_logFile[self.eNB_instance], HTML) + if (logStatus < 0): + HTML.CreateHtmlTestRow(RAN.runtime_stats, 'KO', logStatus) + else: + HTML.CreateHtmlTestRow(RAN.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) + diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 4ac1b0ea94..7da829b7f7 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -42,6 +42,7 @@ import xml.etree.ElementTree as ET import logging import datetime import signal +import statistics as stat from multiprocessing import Process, Lock, SimpleQueue logging.basicConfig( level=logging.DEBUG, @@ -53,6 +54,52 @@ import helpreadme as HELP import constants as CONST import sshconnection + + + +#----------------------------------------------------------- +# Utility functions +#----------------------------------------------------------- + +def GetPingTimeAnalysis(ping_log_file): + #ping time values read from file + t_ping=[] + #ping stats (dictionary) to be returned by the function + ping_stat={} + if (os.path.isfile(ping_log_file)): + with open(ping_log_file,"r") as f: + for line in f: + #looking for time=xxx ms field + result=re.match('^.+time=(?P[0-9\.]+)',line) + if result != None: + t_ping.append(float(result.group('ping_time'))) + + #initial stats + ping_stat['min_0']=min(t_ping) + ping_stat['mean_0']=stat.mean(t_ping) + ping_stat['median_0']=stat.median(t_ping) + ping_stat['max_0']=max(t_ping) + + #get index of max value + + max_loc=t_ping.index(max(t_ping)) + ping_stat['max_loc']=max_loc + #remove it + t_ping.pop(max_loc) + #new stats after removing max value + ping_stat['min_1']=min(t_ping) + ping_stat['mean_1']=stat.mean(t_ping) + ping_stat['median_1']=stat.median(t_ping) + ping_stat['max_1']=max(t_ping) + + return ping_stat + + else: + logging.error("Ping log file does not exist") + return -1 + + + #----------------------------------------------------------- # OaiCiTest Class Definition #----------------------------------------------------------- @@ -185,7 +232,7 @@ class OaiCiTest(): SSH.command('mkdir -p log', '\$', 5) SSH.command('chmod 777 log', '\$', 5) # no need to remove in log (git clean did the trick) - SSH.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 900) + SSH.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 1200) SSH.command('ls ran_build/build', '\$', 3) SSH.command('ls ran_build/build', '\$', 3) buildStatus = True @@ -216,7 +263,7 @@ class OaiCiTest(): HTML.CreateHtmlTabFooter(False) self.ConditionalExit() - def CheckFlexranCtrlInstallation(self,RAN,EPC): + def CheckFlexranCtrlInstallation(self,RAN,EPC,CONTAINERS): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': return SSH = sshconnection.SSHConnection() @@ -225,7 +272,18 @@ class OaiCiTest(): result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) if result is not None: RAN.flexranCtrlInstalled=True + RAN.flexranCtrlIpAddress=EPC.IPAddress logging.debug('Flexran Controller is installed') + else: + # Maybe flexran-rtc is deployed into a container + SSH.command('docker inspect --format="FLEX_RTC_IP_ADDR = {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" prod-flexran-rtc', '\$', 5) + result = re.search('FLEX_RTC_IP_ADDR = (?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + RAN.flexranCtrlDeployed=True + RAN.flexranCtrlIpAddress=result.group('flex_ip_addr') + CONTAINERS.flexranCtrlDeployed=True + CONTAINERS.flexranCtrlIpAddress=result.group('flex_ip_addr') + logging.debug('Flexran Controller is deployed: ' + RAN.flexranCtrlIpAddress) SSH.close() def InitializeFlexranCtrl(self, HTML,RAN,EPC): @@ -547,7 +605,7 @@ class OaiCiTest(): HTML.htmlUEFailureMsg='nr-uesoftmodem did NOT synced' HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') logging.error('\033[91mInitialize OAI UE Failed! \033[0m') - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) def checkDevTTYisUnlocked(self): SSH = sshconnection.SSHConnection() @@ -625,7 +683,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() - def AttachCatM(self,HTML,RAN,COTS_UE): + def AttachCatM(self,HTML,RAN,COTS_UE,EPC): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') @@ -698,7 +756,7 @@ class OaiCiTest(): html_cell = '
CAT-M module Attachment Failed
' html_queue.put(html_cell) HTML.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) def PingCatM(self,HTML,RAN,EPC,COTS_UE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': @@ -709,7 +767,7 @@ class OaiCiTest(): pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) if (pStatus < 0): HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return try: statusQueue = SimpleQueue() @@ -730,7 +788,7 @@ class OaiCiTest(): moduleIPAddr = result.group('ipaddr') else: HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return ping_time = re.findall("-c (\d+)",str(self.ping_args)) device_id = 'catm' @@ -794,7 +852,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) else: HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) except: os.kill(os.getppid(),signal.SIGUSR1) @@ -895,7 +953,7 @@ class OaiCiTest(): pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) if (pStatus < 0): HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return multi_jobs = [] status_queue = SimpleQueue() @@ -914,7 +972,7 @@ class OaiCiTest(): if (status_queue.empty()): HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return else: attach_status = True @@ -943,7 +1001,7 @@ class OaiCiTest(): time.sleep(5) else: HTML.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) def DetachUE_common(self, device_id, idx,COTS_UE): try: @@ -976,7 +1034,7 @@ class OaiCiTest(): pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) if (pStatus < 0): HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return multi_jobs = [] cnt = 0 @@ -1227,6 +1285,8 @@ class OaiCiTest(): if lDataConnectionState == 3: dataConnectionState = 'Data State: SUSPENDED' result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', SSH.getBefore()) + time.sleep(1) + SSH.close() dataConnectionReason = 'Data Reason: UNKNOWN' if result is not None: dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') @@ -1240,7 +1300,6 @@ class OaiCiTest(): qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason statusQueue.put(qMsg) lock.release() - SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1267,12 +1326,12 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: + if (RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted) or RAN.flexranCtrlDeployed: SSH = sshconnection.SSHConnection() SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('cd /opt/flexran_rtc', '\$', 5) - SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) - SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) + SSH.command('curl http://' + RAN.flexranCtrlIpAddress + ':9999/stats | jq \'.\' > check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) + SSH.command('cat check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) result = re.search('Nb Connected UE = (?P[0-9]+)', SSH.getBefore()) passStatus = True if result is not None: @@ -1291,7 +1350,7 @@ class OaiCiTest(): if (status_queue.empty()): HTML.CreateHtmlTestRow(htmlOptions, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) else: check_status = True html_queue = SimpleQueue() @@ -1307,7 +1366,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) else: HTML.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) def GetAllUEIPAddresses(self): SSH = sshconnection.SSHConnection() @@ -1397,17 +1456,26 @@ class OaiCiTest(): if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE): launchFromTrfContainer = True if launchFromTrfContainer: - ping_status = SSH.command('docker exec -it prod-trf-gen /bin/bash -c "ping ' + self.ping_args + ' ' + UE_IPAddress + '" 2>&1 | tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + ping_status = SSH.command('docker exec -it prod-trf-gen /bin/bash -c "ping ' + self.ping_args + ' ' + UE_IPAddress + '" 2>&1 | tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) else: ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + #copy the ping log file to have it locally for analysis (ping stats) + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '.') else: + #ping log file is on the python executor cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' message = cmd + '\n' logging.debug(cmd) ret = subprocess.run(cmd, shell=True) ping_status = ret.returncode + #copy the ping log file to an other folder for log collection (source and destination are EPC) SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + #copy the ping log file to have it locally for analysis (ping stats) + logging.debug(EPC.SourceCodePath + 'ping_' + self.testCase_id + '_' + device_id + '.log') + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath +'/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + #cat is executed on EPC SSH.command('cat ' + EPC.SourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT CASE if ping_status < 0: @@ -1416,6 +1484,7 @@ class OaiCiTest(): SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return + #search is done on cat result result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) if result is None: message = 'Packet Loss Not Found!' @@ -1450,7 +1519,27 @@ class OaiCiTest(): logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + + #adding extra ping stats from local file + ping_log_file='ping_' + self.testCase_id + '_' + device_id + '.log' + logging.debug('Analyzing Ping log file : ' + os.getcwd() + '/' + ping_log_file) + ping_stat=GetPingTimeAnalysis(ping_log_file) + ping_stat_msg='' + if (ping_stat!=-1) and (len(ping_stat)!=0): + ping_stat_msg+='Ping stats before removing largest value : \n' + ping_stat_msg+='RTT(Min) : ' + str("{:.2f}".format(ping_stat['min_0'])) + 'ms \n' + ping_stat_msg+='RTT(Mean) : ' + str("{:.2f}".format(ping_stat['mean_0'])) + 'ms \n' + ping_stat_msg+='RTT(Median) : ' + str("{:.2f}".format(ping_stat['median_0'])) + 'ms \n' + ping_stat_msg+='RTT(Max) : ' + str("{:.2f}".format(ping_stat['max_0'])) + 'ms \n' + ping_stat_msg+='Max Index : ' + str(ping_stat['max_loc']) + '\n' + ping_stat_msg+='Ping stats after removing largest value : \n' + ping_stat_msg+='RTT(Min) : ' + str("{:.2f}".format(ping_stat['min_1'])) + 'ms \n' + ping_stat_msg+='RTT(Mean) : ' + str("{:.2f}".format(ping_stat['mean_1'])) + 'ms \n' + ping_stat_msg+='RTT(Median) : ' + str("{:.2f}".format(ping_stat['median_1'])) + 'ms \n' + ping_stat_msg+='RTT(Max) : ' + str("{:.2f}".format(ping_stat['max_1'])) + 'ms \n' + + #building html message + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + '\n' + ping_stat_msg packetLossOK = True if packetloss is not None: if float(packetloss) > float(self.ping_packetloss_threshold): @@ -1485,7 +1574,7 @@ class OaiCiTest(): pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) if (pStatus < 0): HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) if ping_from_eNB is not None: @@ -1587,12 +1676,12 @@ class OaiCiTest(): pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) if (pStatus < 0): HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return multi_jobs = [] i = 0 @@ -1610,7 +1699,7 @@ class OaiCiTest(): if (status_queue.empty()): HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) else: ping_status = True html_queue = SimpleQueue() @@ -1627,7 +1716,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) else: HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) def Iperf_ComputeTime(self): result = re.search('-t (?P\d+)', str(self.iperf_args)) @@ -1934,15 +2023,34 @@ class OaiCiTest(): ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') if ret.stdout is not None: EPC_Iperf_UE_IPAddress = ret.stdout.strip() + # When using a docker-based deployment, IPERF client shall be launched from trf container + launchFromTrfContainer = False + if re.match('OAI-Rel14-Docker', EPC.Type, re.IGNORECASE): + launchFromTrfContainer = True + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('docker inspect --format="TRF_IP_ADDR = {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" prod-trf-gen', '\$', 5) + result = re.search('TRF_IP_ADDR = (?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + EPC_Iperf_UE_IPAddress = result.group('trf_ip_addr') + SSH.close() port = 5001 + idx + udpOptions = '' + if udpIperf: + udpOptions = '-u ' if launchFromEpc: SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if udpIperf: - SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) + if launchFromTrfContainer: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/iperf-2.0.5/bin/' + SSH.command('docker exec -d prod-trf-gen /bin/bash -c "nohup ' + prefix + 'iperf ' + udpOptions + '-s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &"', '\$', 5) else: - SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) + SSH.command('echo $USER; nohup iperf ' + udpOptions + '-s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) SSH.close() else: if self.ueIperfVersion == self.dummyIperfVersion: @@ -1951,10 +2059,7 @@ class OaiCiTest(): prefix = '' if self.ueIperfVersion == '2.0.5': prefix = '/opt/iperf-2.0.5/bin/' - if udpIperf: - cmd = 'nohup ' + prefix + 'iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - else: - cmd = 'nohup ' + prefix + 'iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + cmd = 'nohup ' + prefix + 'iperf ' + udpOptions + '-s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' logging.debug(cmd) subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') time.sleep(0.5) @@ -2000,13 +2105,16 @@ class OaiCiTest(): # Kill iperf server on EPC side if launchFromEpc: SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) - SSH.command('killall --signal SIGKILL iperf', EPC.UserName, 5) + if launchFromTrfContainer: + SSH.command('docker exec -it prod-trf-gen /bin/bash -c "killall --signal SIGKILL iperf"', '\$', 5) + else: + SSH.command('killall --signal SIGKILL iperf', EPC.UserName, 5) SSH.close() else: cmd = 'killall --signal SIGKILL iperf' logging.debug(cmd) subprocess.run(cmd, shell=True) - time.sleep(1) + time.sleep(1) SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') # in case of failure, retrieve server log if (clientStatus == -1) or (clientStatus == -2): @@ -2014,6 +2122,10 @@ class OaiCiTest(): time.sleep(1) if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + if launchFromTrfContainer: + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('docker cp prod-trf-gen:/iperf-2.0.5/iperf_server_' + self.testCase_id + '_' + device_id + '.log ' + EPC.SourceCodePath + '/scripts', '\$', 5) + SSH.close() SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath+ '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI-UE @@ -2212,8 +2324,16 @@ class OaiCiTest(): else: SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.SourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') # fromdos has to be called on the python executor not on ADB server - cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log' - subprocess.run(cmd, shell=True) + cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 > /dev/null' + try: + subprocess.run(cmd, shell=True) + except: + pass + cmd = 'dos2unix -o iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 > /dev/null' + try: + subprocess.run(cmd, shell=True) + except: + pass self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI UE: @@ -2237,7 +2357,7 @@ class OaiCiTest(): pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) if (pStatus < 0): HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return server_on_enb = re.search('-R', str(self.iperf_args)) if server_on_enb is not None: @@ -2335,7 +2455,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) else: HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) def Iperf(self,HTML,RAN,EPC,COTS_UE): result = re.search('noS1', str(RAN.Initialize_eNB_args)) @@ -2353,13 +2473,13 @@ class OaiCiTest(): pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) if (pStatus < 0): HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): logging.debug('going here') HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) return self.dummyIperfVersion = '2.0.10' @@ -2390,7 +2510,7 @@ class OaiCiTest(): if (status_queue.empty()): HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) else: iperf_status = True iperf_noperf = False @@ -2412,7 +2532,7 @@ class OaiCiTest(): HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) else: HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) def CheckProcessExist(self, check_eNB, check_OAI_UE,RAN,EPC): multi_jobs = [] @@ -2832,7 +2952,7 @@ class OaiCiTest(): job.join() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - def TerminateOAIUE(self,HTML,RAN,COTS_UE): + def TerminateOAIUE(self,HTML,RAN,COTS_UE,EPC): SSH = sshconnection.SSHConnection() SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) @@ -2873,11 +2993,11 @@ class OaiCiTest(): # Not an error then if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): self.Initialize_OAI_UE_args = '' - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) else: if (logStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC): self.Initialize_OAI_UE_args = '' - self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE) + self.AutoTerminateUEandeNB(HTML,RAN,COTS_UE,EPC) else: logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') HTML.htmlUEFailureMsg='' + ueAction + ' Completed\n' + HTML.htmlUEFailureMsg @@ -2886,7 +3006,7 @@ class OaiCiTest(): else: HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - def AutoTerminateUEandeNB(self,HTML,RAN,COTS_UE): + def AutoTerminateUEandeNB(self,HTML,RAN,COTS_UE,EPC): if (self.ADBIPAddress != 'none'): self.testCase_id = 'AUTO-KILL-UE' HTML.testCase_id=self.testCase_id @@ -2900,15 +3020,19 @@ class OaiCiTest(): self.desc = 'Automatic Termination of OAI-UE' HTML.desc='Automatic Termination of OAI-UE' self.ShowTestID() - self.TerminateOAIUE(HTML,RAN,COTS_UE) + self.TerminateOAIUE(HTML,RAN,COTS_UE,EPC) if (RAN.Initialize_eNB_args != ''): - self.testCase_id = 'AUTO-KILL-eNB' + self.testCase_id = 'AUTO-KILL-RAN' HTML.testCase_id=self.testCase_id - self.desc = 'Automatic Termination of eNB' - HTML.desc='Automatic Termination of eNB' + self.desc = 'Automatic Termination of all RAN nodes' + HTML.desc='Automatic Termination of RAN nodes' self.ShowTestID() - RAN.eNB_instance=0 - RAN.TerminateeNB() + #terminate all RAN nodes eNB/gNB/OCP + for instance in range(0, len(RAN.air_interface)): + if RAN.air_interface[instance]!='': + logging.debug('Auto Termination of Instance ' + str(instance) + ' : ' + RAN.air_interface[instance]) + RAN.eNB_instance=instance + RAN.TerminateeNB(HTML,EPC) if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: self.testCase_id = 'AUTO-KILL-flexran-ctl' HTML.testCase_id=self.testCase_id @@ -3050,7 +3174,7 @@ class OaiCiTest(): SSH.command('cd ' + SourceCodePath, '\$', 5) SSH.command('cd cmake_targets', '\$', 5) SSH.command('rm -f build.log.zip', '\$', 5) - SSH.command('zip build.log.zip build_log_*/*', '\$', 60) + SSH.command('zip -r build.log.zip build_log_*/*', '\$', 60) SSH.close() def LogCollectPing(self,EPC): diff --git a/ci-scripts/conf_files/cu.band7.tm1.100PRB.conf b/ci-scripts/conf_files/cu.band7.tm1.100PRB.conf index 42cade271c..e2c94b14ab 100644 --- a/ci-scripts/conf_files/cu.band7.tm1.100PRB.conf +++ b/ci-scripts/conf_files/cu.band7.tm1.100PRB.conf @@ -215,7 +215,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/cu.band7.tm1.25PRB.conf b/ci-scripts/conf_files/cu.band7.tm1.25PRB.conf index 51f7277267..5b994ed29b 100644 --- a/ci-scripts/conf_files/cu.band7.tm1.25PRB.conf +++ b/ci-scripts/conf_files/cu.band7.tm1.25PRB.conf @@ -215,7 +215,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/cu.band7.tm1.50PRB.conf b/ci-scripts/conf_files/cu.band7.tm1.50PRB.conf index 9946713c3a..148c5a9903 100644 --- a/ci-scripts/conf_files/cu.band7.tm1.50PRB.conf +++ b/ci-scripts/conf_files/cu.band7.tm1.50PRB.conf @@ -215,7 +215,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/du.band7.tm1.100PRB.usrpb210.conf b/ci-scripts/conf_files/du.band7.tm1.100PRB.usrpb210.conf index 7167bffa6d..a3ecffb9be 100644 --- a/ci-scripts/conf_files/du.band7.tm1.100PRB.usrpb210.conf +++ b/ci-scripts/conf_files/du.band7.tm1.100PRB.usrpb210.conf @@ -112,7 +112,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/du.band7.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/du.band7.tm1.25PRB.usrpb210.conf index 3c951a2a6e..1920992d70 100644 --- a/ci-scripts/conf_files/du.band7.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/du.band7.tm1.25PRB.usrpb210.conf @@ -112,7 +112,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/du.band7.tm1.50PRB.usrpb210.conf b/ci-scripts/conf_files/du.band7.tm1.50PRB.usrpb210.conf index 4726269312..5df8da05a3 100644 --- a/ci-scripts/conf_files/du.band7.tm1.50PRB.usrpb210.conf +++ b/ci-scripts/conf_files/du.band7.tm1.50PRB.usrpb210.conf @@ -112,7 +112,7 @@ log_config = { NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf index 0c247e9ef9..e70ca78205 100644 --- a/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf @@ -239,7 +239,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf b/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf index f560958e15..400d1a6c9d 100644 --- a/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf +++ b/ci-scripts/conf_files/enb.band13.tm1.50PRB.emtc.conf @@ -448,7 +448,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf index ba81f832db..bd2999b5d5 100644 --- a/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band17.tm1.25PRB.usrpb210.conf @@ -251,7 +251,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf index 79bbd7ee6f..19ef6d0797 100644 --- a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf @@ -395,7 +395,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf index b5fd1255bb..f34878c569 100644 --- a/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm1.100PRB.FairScheduler.usrpb210.conf @@ -228,7 +228,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf index 552dfd637b..e2e482a7c7 100644 --- a/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm1.25PRB.FairScheduler.usrpb210.conf @@ -228,7 +228,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf index d95d2b6ac1..bfea139e92 100644 --- a/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm1.50PRB.FairScheduler.usrpb210.conf @@ -228,7 +228,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf index e466a23ab0..4e0025770b 100644 --- a/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band40.tm2.25PRB.FairScheduler.usrpb210.conf @@ -226,7 +226,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf index e3cdb033c9..1627d21e1a 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.100PRB.usrpb210.conf @@ -247,7 +247,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf index f95530b251..efa1fa64b8 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf @@ -256,7 +256,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf index eddb34a579..f29fc163b3 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf @@ -28,83 +28,85 @@ eNBs = node_function = "3GPP_eNODEB"; node_timing = "synch_to_ext_device"; node_synch_ref = 0; - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2680000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - pbch_repetition = "FALSE"; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 0; - pucch_nCS_AN = 0; - pucch_n1_AN = 0; - pdsch_referenceSignalPower = -25; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ - - pusch_p0_Nominal = -96; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -104; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + pbch_repetition = "FALSE"; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower= -25; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; /* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; + srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =; */ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - ue_TransmissionMode = 1; + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -104; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + ue_TransmissionMode = 1; //Parameters for SIB18 rxPool_sc_CP_Len = "normal"; @@ -116,27 +118,28 @@ eNBs = rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; rxPool_ResourceConfig_offsetIndicator_choice = 0; rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; - rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; -/* rxPool_dataHoppingConfig_hoppingParameter = 0; - rxPool_dataHoppingConfig_numSubbands = "ns1"; - rxPool_dataHoppingConfig_rbOffset = 0; - rxPool_commTxResourceUC-ReqAllowed = "TRUE"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* + rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; */ // Parameters for SIB19 - discRxPool_cp_Len = "normal" - discRxPool_discPeriod = "rf32" - discRxPool_numRetx = 1; - discRxPool_numRepetition = 2; - discRxPool_ResourceConfig_prb_Num = 5; - discRxPool_ResourceConfig_prb_Start = 3; - discRxPool_ResourceConfig_prb_End = 21; - discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; - discRxPool_ResourceConfig_offsetIndicator_choice = 0; - discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; - discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; - discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size= 5; discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; } @@ -204,40 +207,43 @@ eNBs = } ); -MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - phy_test_mode = 0; - puSch10xSnr = 160; - puCch10xSnr = 160; - } +MACRLCs = +( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } ); -L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } +L1s = +( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } ); -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 0 - att_rx = 0; - bands = [7]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 125; - eNB_instances = [0]; - - } +RUs = +( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 125; + eNB_instances = [0]; + } ); -THREAD_STRUCT = ( +THREAD_STRUCT = +( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_SINGLE_THREAD"; @@ -250,27 +256,27 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; }; - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; +log_config : +{ + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; +}; diff --git a/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf index b5d7f35a76..4d89ad96da 100644 --- a/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.50PRB.usrpb210.conf @@ -255,7 +255,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf old mode 100755 new mode 100644 index 19e4abdcb0..33aae14dac --- a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf @@ -266,7 +266,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 118; eNB_instances = [0]; - clock_src = "external"; +# clock_src = "external"; } ); diff --git a/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf index 67cc5706ae..72754165d0 100644 --- a/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band7.tm2.25PRB.usrpb210.conf @@ -249,7 +249,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf index 1b5376644b..da65aad775 100644 --- a/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf @@ -244,7 +244,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "eth0"; - FLEXRAN_IPV4_ADDRESS = "CI_MME_IP_ADDR"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf old mode 100755 new mode 100644 index 0d9691966b..259a2466ad --- a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf +++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf @@ -1,6 +1,8 @@ Active_gNBs = ( "gNB-Eurecom-5GNRBox"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; +Num_Threads_PUSCH = 8 + gNBs = ( @@ -21,7 +23,10 @@ gNBs = ssb_SubcarrierOffset = 31; //0; pdsch_AntennaPorts = 1; - + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + + servingCellConfigCommon = ( { #spCellConfigCommon @@ -260,7 +265,7 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - clock_src = "external"; +# clock_src = "external"; } ); diff --git a/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf index 2bf79a3d7e..d01e4e1c4e 100644 --- a/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band40.tm1.100PRB.FairScheduler.usrpb210.conf @@ -235,7 +235,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf index 6b0e7de659..419598647b 100644 --- a/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band40.tm1.25PRB.FairScheduler.usrpb210.conf @@ -235,7 +235,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf b/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf index 6b41d78506..d4f2eb9ef2 100644 --- a/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band40.tm1.50PRB.FairScheduler.usrpb210.conf @@ -235,7 +235,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf index 5df8f16f78..683fff0bc8 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.100PRB.usrpb210.conf @@ -254,7 +254,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf index ad753bb114..2c3c11b84f 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.25PRB.usrpb210.conf @@ -254,7 +254,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf index dbe3aff3dc..49365a1f61 100644 --- a/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf +++ b/ci-scripts/conf_files/rcc.band7.tm1.if4p5.lo.50PRB.usrpb210.conf @@ -254,7 +254,7 @@ NETWORK_CONTROLLER : { FLEXRAN_ENABLED = "no"; FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_IPV4_ADDRESS = "CI_FLEXRAN_CTL_IP_ADDR"; FLEXRAN_PORT = 2210; FLEXRAN_CACHE = "/mnt/oai_agent_cache"; FLEXRAN_AWAIT_RECONF = "no"; diff --git a/ci-scripts/conf_files/rru.fdd.band7.conf b/ci-scripts/conf_files/rru.fdd.band7.conf index ea923ae371..057f518046 100644 --- a/ci-scripts/conf_files/rru.fdd.band7.conf +++ b/ci-scripts/conf_files/rru.fdd.band7.conf @@ -1,23 +1,25 @@ -RUs = ( - { - local_if_name = "lo"; - remote_address = "127.0.0.1" - local_address = "127.0.0.2"; - local_portc = 50000; - remote_portc = 50000; - local_portd = 50001; - remote_portd = 50001; - local_rf = "yes" - tr_preference = "udp_if4p5"; - nb_tx = 1; - nb_rx = 1; - max_pdschReferenceSignalPower = -27; - max_rxgain = 115; - bands = [7]; - } +RUs = +( + { + local_if_name = "lo"; + remote_address = "127.0.0.1" + local_address = "127.0.0.2"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + local_rf = "yes" + tr_preference = "udp_if4p5"; + nb_tx = 1; + nb_rx = 1; + max_pdschReferenceSignalPower = -27; + max_rxgain = 115; + bands = [7]; + } ); -THREAD_STRUCT = ( +THREAD_STRUCT = +( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_SINGLE_THREAD"; @@ -26,19 +28,20 @@ THREAD_STRUCT = ( } ); -log_config = { - global_log_level ="error"; - global_log_verbosity ="medium"; - hw_log_level ="error"; - hw_log_verbosity ="medium"; - phy_log_level ="error"; - phy_log_verbosity ="medium"; - mac_log_level ="error"; - mac_log_verbosity ="high"; - rlc_log_level ="error"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="error"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="error"; - rrc_log_verbosity ="medium"; +log_config = +{ + global_log_level ="error"; + global_log_verbosity ="medium"; + hw_log_level ="error"; + hw_log_verbosity ="medium"; + phy_log_level ="error"; + phy_log_verbosity ="medium"; + mac_log_level ="error"; + mac_log_verbosity ="high"; + rlc_log_level ="error"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="error"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="error"; + rrc_log_verbosity ="medium"; }; diff --git a/ci-scripts/conf_files/rru.tdd.band40.conf b/ci-scripts/conf_files/rru.tdd.band40.conf index 904f8c9598..5ce3a515f5 100644 --- a/ci-scripts/conf_files/rru.tdd.band40.conf +++ b/ci-scripts/conf_files/rru.tdd.band40.conf @@ -1,23 +1,25 @@ -RUs = ( - { - local_if_name = "lo"; - remote_address = "127.0.0.1" - local_address = "127.0.0.2"; - local_portc = 50000; - remote_portc = 50000; - local_portd = 50001; - remote_portd = 50001; - local_rf = "yes" - tr_preference = "udp_if4p5"; - nb_tx = 1; - nb_rx = 1; - max_pdschReferenceSignalPower = -27; - max_rxgain = 115; - bands = [40]; - } +RUs = +( + { + local_if_name = "lo"; + remote_address = "127.0.0.1" + local_address = "127.0.0.2"; + local_portc = 50000; + remote_portc = 50000; + local_portd = 50001; + remote_portd = 50001; + local_rf = "yes" + tr_preference = "udp_if4p5"; + nb_tx = 1; + nb_rx = 1; + max_pdschReferenceSignalPower = -27; + max_rxgain = 115; + bands = [40]; + } ); -THREAD_STRUCT = ( +THREAD_STRUCT = +( { #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" parallel_config = "PARALLEL_SINGLE_THREAD"; @@ -26,19 +28,20 @@ THREAD_STRUCT = ( } ); -log_config = { - global_log_level ="error"; - global_log_verbosity ="medium"; - hw_log_level ="error"; - hw_log_verbosity ="medium"; - phy_log_level ="error"; - phy_log_verbosity ="medium"; - mac_log_level ="error"; - mac_log_verbosity ="high"; - rlc_log_level ="error"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="error"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="error"; - rrc_log_verbosity ="medium"; +log_config = +{ + global_log_level ="error"; + global_log_verbosity ="medium"; + hw_log_level ="error"; + hw_log_verbosity ="medium"; + phy_log_level ="error"; + phy_log_verbosity ="medium"; + mac_log_level ="error"; + mac_log_verbosity ="high"; + rlc_log_level ="error"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="error"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="error"; + rrc_log_verbosity ="medium"; }; diff --git a/ci-scripts/constants.py b/ci-scripts/constants.py index c5698c5a3e..a0e1ac5c45 100644 --- a/ci-scripts/constants.py +++ b/ci-scripts/constants.py @@ -59,6 +59,7 @@ OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 OAI_UE_PROCESS_SEG_FAULT = -25 OAI_UE_PROCESS_NO_MBMS_MSGS = -26 OAI_UE_PROCESS_OK = +6 +INVALID_PARAMETER = -50 UE_STATUS_DETACHED = 0 UE_STATUS_DETACHING = 1 diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index a1994c5ac3..cd5a747654 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -46,7 +46,6 @@ from multiprocessing import Process, Lock, SimpleQueue import sshconnection as SSH import helpreadme as HELP import constants as CONST -import html #----------------------------------------------------------- # Class Declaration @@ -61,18 +60,18 @@ class EPCManagement(): self.SourceCodePath = '' self.Type = '' self.PcapFileName = '' - self.htmlObj = None self.testCase_id = '' self.MmeIPAddress = '' self.containerPrefix = 'prod' self.mmeConfFile = 'mme.conf' + self.yamlPath = '' #----------------------------------------------------------- # EPC management functions #----------------------------------------------------------- - def InitializeHSS(self): + def InitializeHSS(self, HTML): if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': HELP.GenericHelp(CONST.Version) HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) @@ -114,10 +113,9 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) - def InitializeMME(self): + def InitializeMME(self, HTML): if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': HELP.GenericHelp(CONST.Version) HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) @@ -153,8 +151,7 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) def SetMmeIPAddress(self): # Not an error if we don't need an EPC @@ -175,7 +172,7 @@ class EPCManagement(): else: self.MmeIPAddress = self.IPAddress - def InitializeSPGW(self): + def InitializeSPGW(self, HTML): if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': HELP.GenericHelp(CONST.Version) HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) @@ -212,15 +209,14 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) def CheckHSSProcess(self, status_queue): try: mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-hss /bin/bash -c "ps aux | grep oai_hss"', '\$', 5) + mySSH.command('docker top ' + self.containerPrefix + '-oai-hss', '\$', 5) else: mySSH.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): @@ -245,7 +241,7 @@ class EPCManagement(): mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-mme /bin/bash -c "ps aux | grep oai_mme"', '\$', 5) + mySSH.command('docker top ' + self.containerPrefix + '-oai-mme', '\$', 5) else: mySSH.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): @@ -272,11 +268,11 @@ class EPCManagement(): mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-spgwc /bin/bash -c "ps aux | grep oai_spgwc"', '\$', 5) - result = re.search('oai_spgwc -o -c ', mySSH.getBefore()) + mySSH.command('docker top ' + self.containerPrefix + '-oai-spgwc', '\$', 5) + result = re.search('oai_spgwc -', mySSH.getBefore()) if result is not None: - mySSH.command('docker exec -it ' + self.containerPrefix + '-oai-spgwu-tiny /bin/bash -c "ps aux | grep oai_spgwu"', '\$', 5) - result = re.search('oai_spgwu -o -c ', mySSH.getBefore()) + mySSH.command('docker top ' + self.containerPrefix + '-oai-spgwu-tiny', '\$', 5) + result = re.search('oai_spgwu -', mySSH.getBefore()) elif re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): mySSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) result = re.search('spgwu -c ', mySSH.getBefore()) @@ -297,7 +293,7 @@ class EPCManagement(): except: os.kill(os.getppid(),signal.SIGUSR1) - def TerminateHSS(self): + def TerminateHSS(self, HTML): mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): @@ -330,10 +326,9 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - def TerminateMME(self): + def TerminateMME(self, HTML): mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): @@ -357,10 +352,9 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - def TerminateSPGW(self): + def TerminateSPGW(self, HTML): mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): @@ -401,8 +395,155 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def DeployEpc(self, HTML): + logging.debug('Trying to deploy') + if not re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): + HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) + HTML.CreateHtmlTabFooter(False) + sys.exit('Deploy not possible with this EPC type: ' + self.Type) + + if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': + HELP.GenericHelp(CONST.Version) + HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) + sys.exit('Insufficient EPC Parameters') + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + mySSH.command('docker-compose --version', '\$', 5) + result = re.search('docker-compose version 1', mySSH.getBefore()) + if result is None: + mySSH.close() + HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) + HTML.CreateHtmlTabFooter(False) + sys.exit('docker-compose not installed on ' + self.IPAddress) + + mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5) + mySSH.command('if [ -d ' + self.SourceCodePath + '/logs ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/logs ; fi', '\$', 5) + mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts ' + self.SourceCodePath + '/logs', '\$', 5) + + # deploying and configuring the cassandra database + # container names and services are currently hard-coded. + # they could be recovered by: + # - docker-compose config --services + # - docker-compose config | grep container_name + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + mySSH.copyout(self.IPAddress, self.UserName, self.Password, './' + self.yamlPath + '/docker-compose.yml', self.SourceCodePath + '/scripts') + mySSH.command('wget --quiet --tries=3 --retry-connrefused https://raw.githubusercontent.com/OPENAIRINTERFACE/openair-hss/develop/src/hss_rel14/db/oai_db.cql', '\$', 30) + mySSH.command('docker-compose down', '\$', 60) + mySSH.command('docker-compose up -d db_init', '\$', 60) + + # databases take time... + time.sleep(10) + cnt = 0 + db_init_status = False + while (cnt < 10): + mySSH.command('docker logs prod-db-init', '\$', 5) + result = re.search('OK', mySSH.getBefore()) + if result is not None: + cnt = 10 + db_init_status = True + else: + time.sleep(5) + cnt += 1 + mySSH.command('docker rm -f prod-db-init', '\$', 5) + if not db_init_status: + HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) + HTML.CreateHtmlTabFooter(False) + sys.exit('Cassandra DB deployment/configuration went wrong!') + + # deploying EPC cNFs + mySSH.command('docker-compose up -d oai_spgwu', '\$', 60) + listOfContainers = 'prod-cassandra prod-oai-hss prod-oai-mme prod-oai-spgwc prod-oai-spgwu-tiny' + expectedHealthyContainers = 5 + + # Checking for additional services + mySSH.command('docker-compose config', '\$', 5) + configResponse = mySSH.getBefore() + if configResponse.count('flexran_rtc') == 1: + mySSH.command('docker-compose up -d flexran_rtc', '\$', 60) + listOfContainers += ' prod-flexran-rtc' + expectedHealthyContainers += 1 + if configResponse.count('trf_gen') == 1: + mySSH.command('docker-compose up -d trf_gen', '\$', 60) + listOfContainers += ' prod-trf-gen' + expectedHealthyContainers += 1 + + # Checking if all are healthy + cnt = 0 + while (cnt < 3): + mySSH.command('docker inspect --format=\'{{.State.Health.Status}}\' ' + listOfContainers, '\$', 10) + unhealthyNb = mySSH.getBefore().count('unhealthy') + healthyNb = mySSH.getBefore().count('healthy') - unhealthyNb + startingNb = mySSH.getBefore().count('starting') + if healthyNb == expectedHealthyContainers: + cnt = 10 + else: + time.sleep(10) + cnt += 1 + logging.debug(' -- ' + str(healthyNb) + ' healthy container(s)') + logging.debug(' -- ' + str(unhealthyNb) + ' unhealthy container(s)') + logging.debug(' -- ' + str(startingNb) + ' still starting container(s)') + if healthyNb == expectedHealthyContainers: + mySSH.command('docker exec -d prod-oai-hss /bin/bash -c "nohup tshark -i any -f \'port 9042 or port 3868\' -w /tmp/hss_check_run.pcap 2>&1 > /dev/null"', '\$', 5) + mySSH.command('docker exec -d prod-oai-mme /bin/bash -c "nohup tshark -i any -f \'port 3868 or port 2123 or port 36412\' -w /tmp/mme_check_run.pcap 2>&1 > /dev/null"', '\$', 10) + mySSH.command('docker exec -d prod-oai-spgwc /bin/bash -c "nohup tshark -i any -f \'port 2123 or port 8805\' -w /tmp/spgwc_check_run.pcap 2>&1 > /dev/null"', '\$', 10) + # on SPGW-U, not capturing on SGI to avoid huge file + mySSH.command('docker exec -d prod-oai-spgwu-tiny /bin/bash -c "nohup tshark -i any -f \'port 8805\' -w /tmp/spgwu_check_run.pcap 2>&1 > /dev/null"', '\$', 10) + mySSH.close() + logging.debug('Deployment OK') + HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) + else: + mySSH.close() + logging.debug('Deployment went wrong') + HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) + + def UndeployEpc(self, HTML): + logging.debug('Trying to undeploy') + # No check down, we suppose everything done before. + + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + # Recovering logs and pcap files + mySSH.command('cd ' + self.SourceCodePath + '/logs', '\$', 5) + mySSH.command('docker exec -it prod-oai-hss /bin/bash -c "killall --signal SIGINT oai_hss tshark"', '\$', 5) + mySSH.command('docker exec -it prod-oai-mme /bin/bash -c "killall --signal SIGINT tshark"', '\$', 5) + mySSH.command('docker exec -it prod-oai-spgwc /bin/bash -c "killall --signal SIGINT oai_spgwc tshark"', '\$', 5) + mySSH.command('docker exec -it prod-oai-spgwu-tiny /bin/bash -c "killall --signal SIGINT tshark"', '\$', 5) + mySSH.command('docker logs prod-oai-hss > hss_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('docker logs prod-oai-mme > mme_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('docker logs prod-oai-spgwc > spgwc_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('docker logs prod-oai-spgwu-tiny > spgwu_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('docker cp prod-oai-hss:/tmp/hss_check_run.pcap hss_' + self.testCase_id + '.pcap', '\$', 60) + mySSH.command('docker cp prod-oai-mme:/tmp/mme_check_run.pcap mme_' + self.testCase_id + '.pcap', '\$', 60) + mySSH.command('docker cp prod-oai-spgwc:/tmp/spgwc_check_run.pcap spgwc_' + self.testCase_id + '.pcap', '\$', 60) + mySSH.command('docker cp prod-oai-spgwu-tiny:/tmp/spgwu_check_run.pcap spgwu_' + self.testCase_id + '.pcap', '\$', 60) + # Remove all + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + listOfContainers = 'prod-cassandra prod-oai-hss prod-oai-mme prod-oai-spgwc prod-oai-spgwu-tiny' + nbContainers = 5 + # Checking for additional services + mySSH.command('docker-compose config', '\$', 5) + configResponse = mySSH.getBefore() + if configResponse.count('flexran_rtc') == 1: + listOfContainers += ' prod-flexran-rtc' + nbContainers += 1 + if configResponse.count('trf_gen') == 1: + listOfContainers += ' prod-trf-gen' + nbContainers += 1 + + mySSH.command('docker-compose down', '\$', 60) + mySSH.command('docker inspect --format=\'{{.State.Health.Status}}\' ' + listOfContainers, '\$', 10) + noMoreContainerNb = mySSH.getBefore().count('No such object') + mySSH.command('docker inspect --format=\'{{.Name}}\' prod-oai-public-net prod-oai-private-net', '\$', 10) + noMoreNetworkNb = mySSH.getBefore().count('No such object') + mySSH.close() + if noMoreContainerNb == nbContainers and noMoreNetworkNb == 2: + logging.debug('Undeployment OK') + HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) + else: + logging.debug('Undeployment went wrong') + HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) def LogCollectHSS(self): mySSH = SSH.SSHConnection() @@ -410,9 +551,17 @@ class EPCManagement(): mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) mySSH.command('rm -f hss.log.zip', '\$', 5) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker cp ' + self.containerPrefix + '-oai-hss:/openair-hss/hss_check_run.log .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-hss:/tmp/hss_check_run.pcap .', '\$', 60) - mySSH.command('zip hss.log.zip hss_check_run.*', '\$', 60) + mySSH.command('docker inspect prod-oai-hss', '\$', 10) + result = re.search('No such object', mySSH.getBefore()) + if result is not None: + mySSH.command('cd ../logs', '\$', 5) + mySSH.command('rm -f hss.log.zip', '\$', 5) + mySSH.command('zip hss.log.zip hss_*.*', '\$', 60) + mySSH.command('mv hss.log.zip ../scripts', '\$', 60) + else: + mySSH.command('docker cp ' + self.containerPrefix + '-oai-hss:/openair-hss/hss_check_run.log .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-hss:/tmp/hss_check_run.pcap .', '\$', 60) + mySSH.command('zip hss.log.zip hss_check_run.*', '\$', 60) elif re.match('OAI', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): mySSH.command('zip hss.log.zip hss*.log', '\$', 60) mySSH.command('echo ' + self.Password + ' | sudo -S rm hss*.log', '\$', 5) @@ -432,9 +581,17 @@ class EPCManagement(): mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) mySSH.command('rm -f mme.log.zip', '\$', 5) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker cp ' + self.containerPrefix + '-oai-mme:/openair-mme/mme_check_run.log .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-mme:/tmp/mme_check_run.pcap .', '\$', 60) - mySSH.command('zip mme.log.zip mme_check_run.*', '\$', 60) + mySSH.command('docker inspect prod-oai-mme', '\$', 10) + result = re.search('No such object', mySSH.getBefore()) + if result is not None: + mySSH.command('cd ../logs', '\$', 5) + mySSH.command('rm -f mme.log.zip', '\$', 5) + mySSH.command('zip mme.log.zip mme_*.*', '\$', 60) + mySSH.command('mv mme.log.zip ../scripts', '\$', 60) + else: + mySSH.command('docker cp ' + self.containerPrefix + '-oai-mme:/openair-mme/mme_check_run.log .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-mme:/tmp/mme_check_run.pcap .', '\$', 60) + mySSH.command('zip mme.log.zip mme_check_run.*', '\$', 60) elif re.match('OAI', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): mySSH.command('zip mme.log.zip mme*.log', '\$', 60) mySSH.command('echo ' + self.Password + ' | sudo -S rm mme*.log', '\$', 5) @@ -451,11 +608,19 @@ class EPCManagement(): mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) mySSH.command('rm -f spgw.log.zip', '\$', 5) if re.match('OAI-Rel14-Docker', self.Type, re.IGNORECASE): - mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwc:/openair-spgwc/spgwc_check_run.log .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwu-tiny:/openair-spgwu-tiny/spgwu_check_run.log .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwc:/tmp/spgwc_check_run.pcap .', '\$', 60) - mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwu-tiny:/tmp/spgwu_check_run.pcap .', '\$', 60) - mySSH.command('zip spgw.log.zip spgw*_check_run.*', '\$', 60) + mySSH.command('docker inspect prod-oai-mme', '\$', 10) + result = re.search('No such object', mySSH.getBefore()) + if result is not None: + mySSH.command('cd ../logs', '\$', 5) + mySSH.command('rm -f spgw.log.zip', '\$', 5) + mySSH.command('zip spgw.log.zip spgw*.*', '\$', 60) + mySSH.command('mv spgw.log.zip ../scripts', '\$', 60) + else: + mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwc:/openair-spgwc/spgwc_check_run.log .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwu-tiny:/openair-spgwu-tiny/spgwu_check_run.log .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwc:/tmp/spgwc_check_run.pcap .', '\$', 60) + mySSH.command('docker cp ' + self.containerPrefix + '-oai-spgwu-tiny:/tmp/spgwu_check_run.pcap .', '\$', 60) + mySSH.command('zip spgw.log.zip spgw*_check_run.*', '\$', 60) elif re.match('OAI', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): mySSH.command('zip spgw.log.zip spgw*.log', '\$', 60) mySSH.command('echo ' + self.Password + ' | sudo -S rm spgw*.log', '\$', 5) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 8fbc3b93a0..3094197c54 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -41,6 +41,7 @@ import constants as CONST import cls_oaicitest #main class for OAI CI test framework import cls_physim #class PhySim for physical simulators build and test import cls_cots_ue #class CotsUe for Airplane mode control +import cls_containerize #class Containerize for all container-based operations on RAN/UE objects import sshconnection @@ -98,24 +99,34 @@ def AssignParams(params_dict): def GetParametersFromXML(action): - if action == 'Build_eNB': + if action == 'Build_eNB' or action == 'Build_Image': RAN.Build_eNB_args=test.findtext('Build_eNB_args') + CONTAINERS.imageKind=test.findtext('kind') forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') if (forced_workspace_cleanup is None): RAN.Build_eNB_forced_workspace_cleanup=False + CONTAINERS.forcedWorkspaceCleanup=False else: if re.match('true', forced_workspace_cleanup, re.IGNORECASE): RAN.Build_eNB_forced_workspace_cleanup=True + CONTAINERS.forcedWorkspaceCleanup=True else: - RAN.Build_eNB_forced_workspace_cleanup=False + RAN.Build_eNB_forced_workspace_cleanup=True + CONTAINERS.forcedWorkspaceCleanup=False eNB_instance=test.findtext('eNB_instance') if (eNB_instance is None): RAN.eNB_instance=0 + CONTAINERS.eNB_instance=0 else: RAN.eNB_instance=int(eNB_instance) - RAN.eNB_serverId=test.findtext('eNB_serverId') - if (RAN.eNB_serverId is None): - RAN.eNB_serverId='0' + CONTAINERS.eNB_instance=int(eNB_instance) + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + RAN.eNB_serverId[RAN.eNB_instance]='0' + CONTAINERS.eNB_serverId[RAN.eNB_instance]='0' + else: + RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId + CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId xmlBgBuildField = test.findtext('backgroundBuild') if (xmlBgBuildField is None): RAN.backgroundBuild=False @@ -132,9 +143,11 @@ def GetParametersFromXML(action): RAN.eNB_instance=0 else: RAN.eNB_instance=int(eNB_instance) - RAN.eNB_serverId=test.findtext('eNB_serverId') - if (RAN.eNB_serverId is None): - RAN.eNB_serverId='0' + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + RAN.eNB_serverId[RAN.eNB_instance]='0' + else: + RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId elif action == 'Initialize_eNB': RAN.Initialize_eNB_args=test.findtext('Initialize_eNB_args') @@ -143,9 +156,11 @@ def GetParametersFromXML(action): RAN.eNB_instance=0 else: RAN.eNB_instance=int(eNB_instance) - RAN.eNB_serverId=test.findtext('eNB_serverId') - if (RAN.eNB_serverId is None): - RAN.eNB_serverId='0' + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + RAN.eNB_serverId[RAN.eNB_instance]='0' + else: + RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId #local variable air_interface air_interface = test.findtext('air_interface') @@ -162,10 +177,12 @@ def GetParametersFromXML(action): RAN.eNB_instance=0 else: RAN.eNB_instance=int(eNB_instance) - RAN.eNB_serverId=test.findtext('eNB_serverId') - if (RAN.eNB_serverId is None): - RAN.eNB_serverId='0' - + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + RAN.eNB_serverId[RAN.eNB_instance]='0' + else: + RAN.eNB_serverId[RAN.eNB_instance]=eNB_serverId + #local variable air_interface air_interface = test.findtext('air_interface') if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): @@ -288,6 +305,27 @@ def GetParametersFromXML(action): if (string_field is not None): EPC.mmeConfFile = string_field + elif action == 'Deploy_EPC': + string_field = test.findtext('parameters') + if (string_field is not None): + EPC.yamlPath = string_field + + elif action == 'Deploy_Object' or action == 'Undeploy_Object': + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + CONTAINERS.eNB_instance=0 + else: + CONTAINERS.eNB_instance=int(eNB_instance) + eNB_serverId=test.findtext('eNB_serverId') + if (eNB_serverId is None): + CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]='0' + else: + CONTAINERS.eNB_serverId[CONTAINERS.eNB_instance]=eNB_serverId + string_field = test.findtext('yaml_path') + if (string_field is not None): + CONTAINERS.yamlPath[CONTAINERS.eNB_instance] = string_field + + else: # ie action == 'Run_PhySim': ldpc.runargs = test.findtext('physim_run_args') @@ -339,11 +377,7 @@ SSH = sshconnection.SSHConnection() EPC = epc.EPCManagement() RAN = ran.RANManagement() HTML = html.HTMLManagement() - -EPC.htmlObj=HTML -RAN.htmlObj=HTML -RAN.epcObj=EPC - +CONTAINERS = cls_containerize.Containerize() ldpc=cls_physim.PhySim() #create an instance for LDPC test using GPU or CPU build @@ -354,7 +388,7 @@ ldpc=cls_physim.PhySim() #create an instance for LDPC test using GPU or CPU b #----------------------------------------------------------- import args_parse -py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,HELP) +py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,CONTAINERS,HELP) @@ -383,10 +417,10 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE): if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - RAN.eNB_serverId='0' RAN.eNB_instance=0 + RAN.eNB_serverId[0]='0' RAN.eNBSourceCodePath='/tmp/' - RAN.TerminateeNB() + RAN.TerminateeNB(HTML, EPC) elif re.match('^TerminateUE$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): HELP.GenericHelp(CONST.Version) @@ -398,22 +432,22 @@ elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) - CiTestObj.TerminateOAIUE(HTML,RAN,COTS_UE) + CiTestObj.TerminateOAIUE(HTML,RAN,COTS_UE,EPC) elif re.match('^TerminateHSS$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - EPC.TerminateHSS() + EPC.TerminateHSS(HTML) elif re.match('^TerminateMME$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - EPC.TerminateMME() + EPC.TerminateMME(HTML) elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath== '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - EPC.TerminateSPGW() + EPC.TerminateSPGW(HTML) elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): if (RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): HELP.GenericHelp(CONST.Version) @@ -495,7 +529,7 @@ elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): HTML.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Starting Scenario \u001B[0m') + logging.debug('\u001B[1m Starting Scenario: ' + CiTestObj.testXMLfiles[0] + '\u001B[0m') logging.debug('\u001B[1m----------------------------------------\u001B[0m') if re.match('^TesteNB$', mode, re.IGNORECASE): if RAN.eNBIPAddress == '' or RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '' or EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': @@ -566,7 +600,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re logging.debug('ERROR: requested test is invalidly formatted: ' + test) sys.exit(1) if (EPC.IPAddress != '') and (EPC.IPAddress != 'none'): - CiTestObj.CheckFlexranCtrlInstallation(RAN,EPC) + CiTestObj.CheckFlexranCtrlInstallation(RAN,EPC,CONTAINERS) EPC.SetMmeIPAddress() #get the list of tests to be done @@ -626,17 +660,16 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re RAN.prematureExit = True break if action == 'Build_eNB': - RAN.BuildeNB() + RAN.BuildeNB(HTML) elif action == 'WaitEndBuild_eNB': - RAN.WaitBuildeNBisFinished() + RAN.WaitBuildeNBisFinished(HTML) elif action == 'Initialize_eNB': check_eNB = False check_OAI_UE = False RAN.pStatus=CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE,RAN,EPC) - - RAN.InitializeeNB() + RAN.InitializeeNB(HTML, EPC) elif action == 'Terminate_eNB': - RAN.TerminateeNB() + RAN.TerminateeNB(HTML, EPC) elif action == 'Initialize_UE': CiTestObj.InitializeUE(HTML,COTS_UE) elif action == 'Terminate_UE': @@ -656,17 +689,17 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re elif action == 'Initialize_OAI_UE': CiTestObj.InitializeOAIUE(HTML,RAN,EPC,COTS_UE) elif action == 'Terminate_OAI_UE': - CiTestObj.TerminateOAIUE(HTML,RAN,COTS_UE) + CiTestObj.TerminateOAIUE(HTML,RAN,COTS_UE,EPC) elif action == 'Initialize_CatM_module': CiTestObj.InitializeCatM(HTML) elif action == 'Terminate_CatM_module': CiTestObj.TerminateCatM(HTML) elif action == 'Attach_CatM_module': - CiTestObj.AttachCatM(HTML,RAN,COTS_UE) + CiTestObj.AttachCatM(HTML,RAN,COTS_UE,EPC) elif action == 'Detach_CatM_module': CiTestObj.TerminateCatM(HTML) elif action == 'Ping_CatM_module': - CiTestObj.PingCatM(HTML,RAN,EPC,COTS_UE) + CiTestObj.PingCatM(HTML,RAN,EPC,COTS_UE,EPC) elif action == 'Ping': CiTestObj.Ping(HTML,RAN,EPC,COTS_UE) elif action == 'Iperf': @@ -674,17 +707,21 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re elif action == 'Reboot_UE': CiTestObj.RebootUE(HTML,RAN,EPC) elif action == 'Initialize_HSS': - EPC.InitializeHSS() + EPC.InitializeHSS(HTML) elif action == 'Terminate_HSS': - EPC.TerminateHSS() + EPC.TerminateHSS(HTML) elif action == 'Initialize_MME': - EPC.InitializeMME() + EPC.InitializeMME(HTML) elif action == 'Terminate_MME': - EPC.TerminateMME() + EPC.TerminateMME(HTML) elif action == 'Initialize_SPGW': - EPC.InitializeSPGW() + EPC.InitializeSPGW(HTML) elif action == 'Terminate_SPGW': - EPC.TerminateSPGW() + EPC.TerminateSPGW(HTML) + elif action == 'Deploy_EPC': + EPC.DeployEpc(HTML) + elif action == 'Undeploy_EPC': + EPC.UndeployEpc(HTML) elif action == 'Initialize_FlexranCtrl': CiTestObj.InitializeFlexranCtrl(HTML,RAN,EPC) elif action == 'Terminate_FlexranCtrl': @@ -698,6 +735,12 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re if ldpc.exitStatus==1:sys.exit() elif action == 'Run_PhySim': HTML=ldpc.Run_PhySim(HTML,CONST,id) + elif action == 'Build_Image': + CONTAINERS.BuildImage(HTML) + elif action == 'Deploy_Object': + CONTAINERS.DeployObject(HTML, EPC) + elif action == 'Undeploy_Object': + CONTAINERS.UndeployObject(HTML, RAN) else: sys.exit('Invalid class (action) from xml') if not RAN.prematureExit: @@ -707,14 +750,14 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re HTML.testStabilityPointReached = True CiTestObj.FailReportCnt += 1 if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.prematureExit: - logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') + logging.debug('Scenario failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') HTML.CreateHtmlTabFooter(False) if CiTestObj.testUnstable and (CiTestObj.testStabilityPointReached or CiTestObj.testMinStableId == '999999'): logging.debug('Scenario has reached minimal stability point -- Not a Failure') else: sys.exit('Failed Scenario') else: - logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') + logging.info('Scenario passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') HTML.CreateHtmlTabFooter(True) elif re.match('^LoadParams$', mode, re.IGNORECASE): pass diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 6425d55c8f..774d7f19c6 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -42,10 +42,8 @@ from multiprocessing import Process, Lock, SimpleQueue # OAI Testing modules #----------------------------------------------------------- import sshconnection as SSH -import epc import helpreadme as HELP import constants as CONST -import html #----------------------------------------------------------- # Class Declaration @@ -77,19 +75,20 @@ class RANManagement(): self.backgroundBuildTestId = ['', '', ''] self.Build_eNB_forced_workspace_cleanup = False self.Initialize_eNB_args = '' + self.imageKind = '' self.air_interface = ['', '', ''] #changed from 'lte' to '' may lead to side effects in main self.eNB_instance = 0 - self.eNB_serverId = '' + self.eNB_serverId = ['', '', ''] self.eNBLogFiles = ['', '', ''] self.eNBOptions = ['', '', ''] self.eNBmbmsEnables = [False, False, False] self.eNBstatuses = [-1, -1, -1] self.flexranCtrlInstalled = False self.flexranCtrlStarted = False + self.flexranCtrlDeployed = False + self.flexranCtrlIpAddress = '' self.testCase_id = '' self.epcPcapFile = '' - self.htmlObj = None - self.epcObj = None self.runtime_stats= '' @@ -98,21 +97,21 @@ class RANManagement(): # RAN management functions #----------------------------------------------------------- - def BuildeNB(self): + def BuildeNB(self, HTML): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - if self.eNB_serverId == '0': + if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': + elif self.eNB_serverId[self.eNB_instance] == '1': lIpAddr = self.eNB1IPAddress lUserName = self.eNB1UserName lPassWord = self.eNB1Password lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': + elif self.eNB_serverId[self.eNB_instance] == '2': lIpAddr = self.eNB2IPAddress lUserName = self.eNB2UserName lPassWord = self.eNB2Password @@ -120,6 +119,7 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + logging.debug('Building on server: ' + lIpAddr) mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) @@ -137,10 +137,7 @@ class RANManagement(): # Worakround for some servers, we need to erase completely the workspace if self.Build_eNB_forced_workspace_cleanup: mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) - if self.htmlObj is not None: - self.testCase_id = self.htmlObj.testCase_id - else: - self.testCase_id = '000000' + self.testCase_id = HTML.testCase_id # on RedHat/CentOS .git extension is mandatory result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) if result is not None: @@ -181,8 +178,7 @@ class RANManagement(): mismatch = True if not mismatch: mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) return mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) @@ -209,26 +205,25 @@ class RANManagement(): mySSH.command('echo ' + lPassWord + ' | sudo -S ls', '\$', 5) mySSH.command('echo $USER; nohup sudo -E ./my-lte-softmodem-build.sh' + ' > ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ' + ' 2>&1 &', lUserName, 5) mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id return mySSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) mySSH.close() - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id, HTML) - def WaitBuildeNBisFinished(self): - if self.eNB_serverId == '0': + def WaitBuildeNBisFinished(self, HTML): + if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': + elif self.eNB_serverId[self.eNB_instance] == '1': lIpAddr = self.eNB1IPAddress lUserName = self.eNB1UserName lPassWord = self.eNB1Password lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': + elif self.eNB_serverId[self.eNB_instance] == '2': lIpAddr = self.eNB2IPAddress lUserName = self.eNB2UserName lPassWord = self.eNB2Password @@ -236,6 +231,7 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + logging.debug('Waiting for end of build on server: ' + lIpAddr) mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) count = 40 @@ -249,11 +245,10 @@ class RANManagement(): count -= 1 time.sleep(30) mySSH.close() - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)], HTML) - def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): - if self.htmlObj is not None: - self.htmlObj.testCase_id=testcaseId + def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId, HTML): + HTML.testCase_id=testcaseId mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) @@ -284,7 +279,7 @@ class RANManagement(): mySSH.command('mkdir -p build_log_' + testcaseId, '\$', 5) mySSH.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) mySSH.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) - if self.eNB_serverId != '0': + if self.eNB_serverId[self.eNB_instance] != '0': mySSH.command('cd cmake_targets', '\$', 5) mySSH.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) mySSH.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) @@ -307,27 +302,25 @@ class RANManagement(): #generate logging info depending on buildStatus and air interface if buildStatus: logging.info('\u001B[1m Building OAI ' + self.air_interface[self.eNB_instance] + ' Pass\u001B[0m') - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) else: logging.error('\u001B[1m Building OAI ' + self.air_interface[self.eNB_instance] + ' Failed\u001B[0m') - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'KO', CONST.ALL_PROCESSES_OK) - self.htmlObj.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.Build_eNB_args, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTabFooter(False) sys.exit(1) - def InitializeeNB(self): - if self.eNB_serverId == '0': + def InitializeeNB(self, HTML, EPC): + if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': + elif self.eNB_serverId[self.eNB_instance] == '1': lIpAddr = self.eNB1IPAddress lUserName = self.eNB1UserName lPassWord = self.eNB1Password lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': + elif self.eNB_serverId[self.eNB_instance] == '2': lIpAddr = self.eNB2IPAddress lUserName = self.eNB2UserName lPassWord = self.eNB2Password @@ -335,24 +328,21 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + logging.debug('Starting eNB/gNB on server: ' + lIpAddr) - if self.htmlObj is not None: - self.testCase_id = self.htmlObj.testCase_id - else: - self.testCase_id = '000000' + self.testCase_id = HTML.testCase_id mySSH = SSH.SSHConnection() if (self.pStatus < 0): - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' ' + self.Initialize_eNB_args, 'KO', self.pStatus) - self.htmlObj.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' ' + self.Initialize_eNB_args, 'KO', self.pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if (result is not None) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.IPAddress - localEpcUserName = self.epcObj.UserName - localEpcPassword = self.epcObj.Password + if (result is not None): + localEpcIpAddr = EPC.IPAddress + localEpcUserName = EPC.UserName + localEpcPassword = EPC.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) mySSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', mySSH.getBefore()) @@ -400,17 +390,17 @@ class RANManagement(): mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) # Make a copy and adapt to EPC / eNB IP addresses mySSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - if self.epcObj is not None: - localMmeIpAddr = self.epcObj.MmeIPAddress - mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + localMmeIpAddr + '/\' ' + ci_full_config_file, '\$', 2); + localMmeIpAddr = EPC.MmeIPAddress + mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + localMmeIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_GNB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_FR1_CTL_ENB_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - if self.flexranCtrlInstalled and self.flexranCtrlStarted: + if (self.flexranCtrlInstalled and self.flexranCtrlStarted) or self.flexranCtrlDeployed: mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_FLEXRAN_CTL_IP_ADDR/' + self.flexranCtrlIpAddress + '/\' ' + ci_full_config_file, '\$', 2); else: mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); self.eNBmbmsEnables[int(self.eNB_instance)] = False @@ -452,14 +442,13 @@ class RANManagement(): mySSH.close() doLoop = False logging.error('\u001B[1;37;41m eNB/gNB/ocp-eNB logging system did not show got sync! \u001B[0m') - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if (result is not None) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.IPAddress - localEpcUserName = self.epcObj.UserName - localEpcPassword = self.epcObj.Password + if (result is not None): + localEpcIpAddr = EPC.IPAddress + localEpcUserName = EPC.UserName + localEpcPassword = EPC.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) @@ -507,11 +496,10 @@ class RANManagement(): else: logging.error('\u001B[1m oaitun_enm1 interface is either NOT mounted or NOT configured\u001B[0m') if enbDidSync: - self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId) + self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId[self.eNB_instance]) mySSH.close() - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) logging.debug('\u001B[1m Initialize eNB/gNB/ocp-eNB Completed\u001B[0m') def CheckeNBProcess(self, status_queue): @@ -546,18 +534,18 @@ class RANManagement(): except: os.kill(os.getppid(),signal.SIGUSR1) - def TerminateeNB(self): - if self.eNB_serverId == '0': + def TerminateeNB(self, HTML, EPC): + if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': + elif self.eNB_serverId[self.eNB_instance] == '1': lIpAddr = self.eNB1IPAddress lUserName = self.eNB1UserName lPassWord = self.eNB1Password lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': + elif self.eNB_serverId[self.eNB_instance] == '2': lIpAddr = self.eNB2IPAddress lUserName = self.eNB2UserName lPassWord = self.eNB2Password @@ -565,6 +553,7 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') + logging.debug('Stopping eNB/gNB on server: ' + lIpAddr) mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) @@ -586,10 +575,10 @@ class RANManagement(): mySSH.close() # If tracer options is on, stopping tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if (result is not None) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.IPAddress - localEpcUserName = self.epcObj.UserName - localEpcPassword = self.epcObj.Password + if (result is not None): + localEpcIpAddr = EPC.IPAddress + localEpcUserName = EPC.UserName + localEpcPassword = EPC.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) @@ -613,9 +602,8 @@ class RANManagement(): mySSH.close() mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) + logStatus = self.AnalyzeLogFile_eNB(extracted_log_file, HTML) + HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) self.eNBLogFiles[int(self.eNB_instance)] = '' else: analyzeFile = False @@ -627,27 +615,23 @@ class RANManagement(): copyin_res = mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') - if self.htmlObj is not None: - self.htmlObj.htmleNBFailureMsg='Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' - self.htmlObj.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + HTML.htmleNBFailureMsg='Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.eNBmbmsEnables[int(self.eNB_instance)] = False return - if self.eNB_serverId != '0': + if self.eNB_serverId[self.eNB_instance] != '0': mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze) - logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) + logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze, HTML) if (logStatus < 0): - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('N/A', 'KO', logStatus) + HTML.CreateHtmlTestRow('N/A', 'KO', logStatus) self.preamtureExit = True self.eNBmbmsEnables[int(self.eNB_instance)] = False return else: - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) else: - if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK) self.eNBmbmsEnables[int(self.eNB_instance)] = False self.eNBstatuses[int(self.eNB_instance)] = -1 @@ -661,7 +645,7 @@ class RANManagement(): mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) mySSH.close() - def AnalyzeLogFile_eNB(self, eNBlogFile): + def AnalyzeLogFile_eNB(self, eNBlogFile, HTML): if (not os.path.isfile('./' + eNBlogFile)): return -1 enb_log_file = open('./' + eNBlogFile, 'r') @@ -709,7 +693,11 @@ class RANManagement(): NSA_RAPROC_PUSCH_check = 0 #dlsch and ulsch statistics (dictionary) dlsch_ulsch_stats = {} - + #count "L1 thread not ready" msg + L1_thread_not_ready_cnt = 0 + #count "problem receiving samples" msg + pb_receiving_samples_cnt = 0 + for line in enb_log_file.readlines(): # Runtime statistics result = re.search('Run time:' ,str(line)) @@ -874,6 +862,15 @@ class RANManagement(): if result is not None: #remove 1- all useless char before relevant info (ulsch or dlsch) 2- trailing char dlsch_ulsch_stats[k]=re.sub(r'^.*\]\s+', r'' , line.rstrip()) + #count "L1 thread not ready" msg + result = re.search('\[PHY\]\s+L1_thread isn\'t ready', str(line)) + if result is not None: + L1_thread_not_ready_cnt += 1 + #count "problem receiving samples" msg + result = re.search('\[PHY\]\s+problem receiving samples', str(line)) + if result is not None: + pb_receiving_samples_cnt += 1 + enb_log_file.close() logging.debug(' File analysis completed') if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): @@ -903,6 +900,17 @@ class RANManagement(): htmlMsg = statMsg+'\n' logging.debug(statMsg) htmleNBFailureMsg += htmlMsg + #L1 thread not ready log + statMsg = '[PHY] L1 thread is not ready msg count = '+str(L1_thread_not_ready_cnt) + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + #problem receiving samples log + statMsg = '[PHY] problem receiving samples msg count = '+str(pb_receiving_samples_cnt) + htmlMsg = statMsg+'\n' + logging.debug(statMsg) + htmleNBFailureMsg += htmlMsg + #ulsch and dlsch statistics if len(dlsch_ulsch_stats)!=0: #check if dictionary is not empty statMsg='' @@ -1018,8 +1026,7 @@ class RANManagement(): logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') htmleNBFailureMsg += rlcMsg + '\n' global_status = CONST.ENB_PROCESS_REALTIME_ISSUE - if self.htmlObj is not None: - self.htmlObj.htmleNBFailureMsg=htmleNBFailureMsg + HTML.htmleNBFailureMsg=htmleNBFailureMsg # Runtime statistics for console output and HTML if runTime != '': logging.debug(runTime) diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 6c87f5dac3..70eabb7b69 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -2200,7 +2200,7 @@ function run_test_on_vm { mkdir --parents $ARCHIVES_LOC fi - local try_cnt="0" + local try_cnt=0 NR_STATUS=0 ######### start of RA TEST loop @@ -2232,7 +2232,7 @@ function run_test_on_vm { scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC SYNC_STATUS=-1 - try_cnt=$[$try_cnt+1] + try_cnt=$((try_cnt+1)) continue fi @@ -2255,9 +2255,10 @@ function run_test_on_vm { if [ $RA_STATUS -ne 0 ] then echo "RA test NOT OK" - try_cnt=$[$try_cnt+1] + echo "try_cnt = " $try_cnt + try_cnt=$((try_cnt+1)) else - try_cnt=$[$try_cnt+10] + try_cnt=$((try_cnt+10)) fi done ########### end RA test @@ -2266,7 +2267,7 @@ function run_test_on_vm { ######### start of PHY TEST loop - try_cnt="0" + try_cnt=0 while [ $try_cnt -lt 4 ] do @@ -2297,7 +2298,7 @@ function run_test_on_vm { scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC SYNC_STATUS=-1 - try_cnt=$[$try_cnt+1] + try_cnt=$((try_cnt+1)) continue fi @@ -2337,7 +2338,7 @@ function run_test_on_vm { terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC - try_cnt=$[$try_cnt+1] + try_cnt=$((try_cnt+1)) continue fi @@ -2363,9 +2364,9 @@ function run_test_on_vm { if [ $IPERF_STATUS -ne 0 ] then echo "UL test not OK" - try_cnt=$[$try_cnt+1] + try_cnt=$((try_cnt+1)) else - try_cnt=$[$try_cnt+10] + try_cnt=$((try_cnt+10)) fi done ######### end of loop diff --git a/ci-scripts/tcp_iperf_stats.awk b/ci-scripts/tcp_iperf_stats.awk index 3a00e4555f..b21bf16a2f 100644 --- a/ci-scripts/tcp_iperf_stats.awk +++ b/ci-scripts/tcp_iperf_stats.awk @@ -21,7 +21,11 @@ BEGIN{max=0;min=10000} { if ($0 ~/Mbits/) { - split($0,a,"MBytes") + if ($0 ~/KBytes/) { + split($0,a,"KBytes") + } else { + split($0,a,"MBytes") + } split(a[2],b) if (b[1]>max) { max=b[1] diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index 2c20988851..0e00a2e7d4 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -19,6 +19,8 @@ - Reboot_UE - Initialize_FlexranCtrl - Terminate_FlexranCtrl + - Deploy_EPC + - Undeploy_EPC - Initialize_HSS - Terminate_HSS - Initialize_MME @@ -32,3 +34,6 @@ - Ping_CatM_module - IdleSleep - Perform_X2_Handover + - Build_Image + - Deploy_Object + - Undeploy_Object diff --git a/ci-scripts/xml_files/enb_ue_usrp210_band7_ue_build.xml b/ci-scripts/xml_files/enb_ue_usrp210_band7_ue_build.xml index 7280a87fb8..d73a1e26e9 100644 --- a/ci-scripts/xml_files/enb_ue_usrp210_band7_ue_build.xml +++ b/ci-scripts/xml_files/enb_ue_usrp210_band7_ue_build.xml @@ -32,7 +32,7 @@ Build_OAI_UE Build OAI UE - -w USRP --UE + -w USRP --UE --ninja diff --git a/ci-scripts/xml_files/fr1_image_build.xml b/ci-scripts/xml_files/fr1_image_build.xml new file mode 100644 index 0000000000..9dd386b646 --- /dev/null +++ b/ci-scripts/xml_files/fr1_image_build.xml @@ -0,0 +1,40 @@ + + + build-tab + Build + wrench + + 000001 + + + + + Build_Image + Build eNB Image + all + 0 + 0 + + + diff --git a/ci-scripts/xml_files/fr1_oai_cn_deploy.xml b/ci-scripts/xml_files/fr1_oai_cn_deploy.xml new file mode 100644 index 0000000000..919def7aa3 --- /dev/null +++ b/ci-scripts/xml_files/fr1_oai_cn_deploy.xml @@ -0,0 +1,39 @@ + + + epc-deploy-tab + EPC-Deploy + log-in + + 000100 + + + + + + Deploy_EPC + Deploy all EPC containers + yaml_files/fr1_epc_tim + + + diff --git a/ci-scripts/xml_files/fr1_oai_cn_undeploy.xml b/ci-scripts/xml_files/fr1_oai_cn_undeploy.xml new file mode 100644 index 0000000000..76192efea1 --- /dev/null +++ b/ci-scripts/xml_files/fr1_oai_cn_undeploy.xml @@ -0,0 +1,38 @@ + + + epc-undeploy-tab + EPC-Undeploy + log-out + + 000200 + + + + + + Undeploy_EPC + Undeploy all EPC containers + + + diff --git a/ci-scripts/xml_files/fr1_ran_ue_base.xml b/ci-scripts/xml_files/fr1_ran_ue_base.xml new file mode 100644 index 0000000000..847967f81e --- /dev/null +++ b/ci-scripts/xml_files/fr1_ran_ue_base.xml @@ -0,0 +1,150 @@ + + + TEST-FR1-TM1 + FR1 + tasks + + 010000 + 030000 + 040000 + 010001 + 000001 + 050000 + 050001 + 050002 + 050002 + 000001 + 060000 + 060001 + 000001 + 010002 + 000001 + 070001 + 070000 + 010003 + + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf + 0 + 0 + lte + + + + + Initialize_eNB + Initialize gNB + -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E + 1 + 1 + nr + + + + IdleSleep + Sleep + 20 + + + + Ping + Ping: 20pings in 20sec + -c 20 + 50 + + + + Ping + Ping: 5pings in 1sec + -c 5 -i 0.2 + 50 + + + + Ping + Ping: 100pings in 20sec + -c 100 -i 0.2 + 50 + + + + + Iperf + iperf (DL/1Mbps/UDP)(30 sec)(single-ue profile) + -u -b 1M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/1Mbps/UDP)(30 sec)(single-ue profile) + -u -b 1M -t 30 -i 1 -R + 50 + single-ue + + + + Terminate_eNB + Terminate eNB + 0 + 0 + lte + + + + Terminate_eNB + Terminate gNB + 1 + 1 + nr + + + + diff --git a/ci-scripts/xml_files/fr1_ran_ue_proc.xml b/ci-scripts/xml_files/fr1_ran_ue_iperf.xml similarity index 83% rename from ci-scripts/xml_files/fr1_ran_ue_proc.xml rename to ci-scripts/xml_files/fr1_ran_ue_iperf.xml index 330fb27f21..8ead3afc62 100644 --- a/ci-scripts/xml_files/fr1_ran_ue_proc.xml +++ b/ci-scripts/xml_files/fr1_ran_ue_iperf.xml @@ -31,10 +31,14 @@ 010001 000001 050000 - 050001 + 000001 + 060000 + 060001 + 000001 + 010002 + 000001 070001 070000 - 010002 010003 @@ -92,11 +96,21 @@ 50 - - Ping - Ping: 5pings in 1sec - -c 5 -i 0.2 - 50 + + + Iperf + iperf (DL/2.5Mbps/UDP)(60 sec)(single-ue profile) + -u -b 2.5M -t 60 -i 1 + 50 + single-ue + + + + Iperf + iperf (UL/1.5Mbps/UDP)(60 sec)(single-ue profile) + -u -b 1.5M -t 60 -i 1 -R + 50 + single-ue diff --git a/ci-scripts/xml_files/fr1_usrp210_band7_deploy_test_05mhz_tm1.xml b/ci-scripts/xml_files/fr1_usrp210_band7_deploy_test_05mhz_tm1.xml new file mode 100644 index 0000000000..3d04fdeb29 --- /dev/null +++ b/ci-scripts/xml_files/fr1_usrp210_band7_deploy_test_05mhz_tm1.xml @@ -0,0 +1,133 @@ + + + test-deploy-enb-mono + Test-Deploy-eNB-Mono + tasks + 1 + + 040101 + 030101 000020 040301 000021 040501 040601 040611 040641 040651 040401 040201 030201 + + + + + IdleSleep + Waiting for 60 seconds + 60 + + + + IdleSleep + Waiting for 10 seconds + 10 + + + + CheckStatusUE + Check UE(s) status before attachment + 0 + + + + CheckStatusUE + Check UE(s) status after attachment + 1 + + + + Deploy_Object + Deploy eNB (FDD/Band7/5MHz) in a container + ci-scripts/yaml_files/fr1_enb_mono_fdd_tim + 0 + 0 + + + + Undeploy_Object + Undeploy eNB + ci-scripts/yaml_files/fr1_enb_mono_fdd_tim + 0 + 0 + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec) + -u -b 15M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/TCP)(30 sec) + -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/7.5Mbps/UDP)(30 sec) + -u -b 7.5M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/TCP)(30 sec) + -t 30 -i 1 -R + 50 + single-ue + + + diff --git a/ci-scripts/xml_files/ue_band20_build.xml b/ci-scripts/xml_files/ue_band20_build.xml index 9ca1a2b234..d867929630 100644 --- a/ci-scripts/xml_files/ue_band20_build.xml +++ b/ci-scripts/xml_files/ue_band20_build.xml @@ -32,7 +32,7 @@ Build_OAI_UE Build OAI UE - -w USRP --UE + -w USRP --UE --ninja 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 new file mode 100644 index 0000000000..2df277d78b --- /dev/null +++ b/ci-scripts/yaml_files/fr1_enb_mono_fdd_tim/docker-compose.yml @@ -0,0 +1,49 @@ +version: '3.8' + +services: + enb_mono_fdd: + image: oai-enb:latest + privileged: true + container_name: prod-enb-mono-fdd + environment: + USE_FDD_MONO: 'yes' + USE_B2XX: 'yes' + ENB_NAME: eNB-in-docker + MCC: '222' + MNC: '01' + MNC_LENGTH: 2 + TAC: 1 + UTRA_BAND_ID: 7 + DL_FREQUENCY_IN_MHZ: 2680 + UL_FREQUENCY_OFFSET_IN_MHZ: 120 + NID_CELL: 10 + NB_PRB: 25 + MME_S1C_IP_ADDRESS: CI_MME_IP_ADDR + ENB_S1C_IF_NAME: eth0 + ENB_S1C_IP_ADDRESS: 192.168.61.30 + ENB_S1U_IF_NAME: eth0 + ENB_S1U_IP_ADDRESS: 192.168.61.30 + ENB_X2_IP_ADDRESS: 192.168.61.30 + FLEXRAN_ENABLED: 'no' + FLEXRAN_INTERFACE_NAME: eth0 + FLEXRAN_IPV4_ADDRESS: CI_FLEXRAN_CTL_IP_ADDR + USE_ADDITIONAL_OPTIONS: '--RUs.[0].max_rxgain 115 --RUs.[0].max_pdschReferenceSignalPower -27 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96' + volumes: + - /dev:/dev + networks: + public_net: + ipv4_address: 192.168.61.30 + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + name: prod-oai-public-net + ipam: + config: + - subnet: 192.168.61.0/26 + diff --git a/ci-scripts/yaml_files/fr1_epc_tim/docker-compose.yml b/ci-scripts/yaml_files/fr1_epc_tim/docker-compose.yml new file mode 100644 index 0000000000..28ae154838 --- /dev/null +++ b/ci-scripts/yaml_files/fr1_epc_tim/docker-compose.yml @@ -0,0 +1,203 @@ +version: '3.8' + +services: + cassandra: + image: cassandra:2.1 + container_name: prod-cassandra + networks: + private_net: + ipv4_address: 192.168.68.2 + environment: + CASSANDRA_CLUSTER_NAME: "OAI HSS Cluster" + CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch + healthcheck: + test: /bin/bash -c "nodetool status" + interval: 10s + timeout: 5s + retries: 5 + + db_init: + image: cassandra:2.1 + container_name: prod-db-init + depends_on: [cassandra] + deploy: + restart_policy: + condition: on-failure + max_attempts: 10 + networks: + private_net: + ipv4_address: 192.168.68.4 + volumes: + - ./oai_db.cql:/home/oai_db.cql + entrypoint: /bin/bash -c "cqlsh --file /home/oai_db.cql 192.168.68.2 && echo 'OK'" + + oai_hss: + image: oai-hss:production + container_name: prod-oai-hss + privileged: true + depends_on: [cassandra] + networks: + private_net: + ipv4_address: 192.168.68.3 + public_net: + ipv4_address: 192.168.61.2 + environment: + REALM: openairinterface.org + HSS_FQDN: hss.openairinterface.org + PREFIX: /openair-hss/etc + cassandra_Server_IP: 192.168.68.2 + OP_KEY: 1006020f0a478bf6b699f15c062e42b3 + LTE_K: fec86ba6eb707ed08905757b1bb44b8f + APN1: oai.ipv4 + APN2: internet + FIRST_IMSI: 222010100001120 + NB_USERS: 10 + healthcheck: + test: /bin/bash -c "pgrep oai_hss" + interval: 10s + timeout: 5s + retries: 5 + + oai_mme: + image: oai-mme:production + container_name: prod-oai-mme + privileged: true + depends_on: [oai_hss] + networks: + public_net: + ipv4_address: 192.168.61.3 + environment: + REALM: openairinterface.org + PREFIX: /openair-mme/etc + INSTANCE: 1 + PID_DIRECTORY: /var/run + HSS_IP_ADDR: 192.168.61.2 + HSS_HOSTNAME: hss + HSS_FQDN: hss.openairinterface.org + HSS_REALM: openairinterface.org + MCC: '222' + MNC: '01' + MME_GID: 32768 + MME_CODE: 3 + TAC_0: 1 + TAC_1: 2 + TAC_2: 3 + MME_FQDN: mme.openairinterface.org + MME_S6A_IP_ADDR: 192.168.61.3 + MME_INTERFACE_NAME_FOR_S1_MME: eth0 + MME_IPV4_ADDRESS_FOR_S1_MME: 192.168.61.3 + MME_INTERFACE_NAME_FOR_S11: eth0 + MME_IPV4_ADDRESS_FOR_S11: 192.168.61.3 + MME_INTERFACE_NAME_FOR_S10: lo + MME_IPV4_ADDRESS_FOR_S10: 127.0.0.10 + OUTPUT: CONSOLE + SGW_IPV4_ADDRESS_FOR_S11_0: 192.168.61.4 + PEER_MME_IPV4_ADDRESS_FOR_S10_0: 0.0.0.0 + PEER_MME_IPV4_ADDRESS_FOR_S10_1: 0.0.0.0 + MCC_SGW_0: '222' + MNC3_SGW_0: '001' + TAC_LB_SGW_0: '01' + TAC_HB_SGW_0: '00' + MCC_MME_0: '222' + MNC3_MME_0: '001' + TAC_LB_MME_0: '02' + TAC_HB_MME_0: '00' + MCC_MME_1: '222' + MNC3_MME_1: '001' + TAC_LB_MME_1: '03' + TAC_HB_MME_1: '00' + TAC_LB_SGW_TEST_0: '03' + TAC_HB_SGW_TEST_0: '00' + SGW_IPV4_ADDRESS_FOR_S11_TEST_0: 0.0.0.0 + healthcheck: + test: /bin/bash -c "pgrep oai_mme" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwc: + image: oai-spgwc:production + privileged: true + depends_on: [oai_mme] + container_name: prod-oai-spgwc + networks: + public_net: + ipv4_address: 192.168.61.4 + environment: + PID_DIRECTORY: /var/run + SGW_INTERFACE_NAME_FOR_S11: eth0 + SGW_IP_FOR_S5_S8_CP: 127.0.0.11/8 + PGW_IP_FOR_S5_S8_CP: 127.0.0.12/8 + PGW_INTERFACE_NAME_FOR_SX: eth0 + DEFAULT_APN: oai.ipv4 + DEFAULT_DNS_IPV4_ADDRESS: 192.168.18.129 + DEFAULT_DNS_SEC_IPV4_ADDRESS: 8.8.4.4 + UE_IP_ADDRESS_POOL: '12.1.1.2 - 12.1.1.254' + PUSH_PROTOCOL_OPTION: 'yes' + healthcheck: + test: /bin/bash -c "pgrep oai_spgwc" + interval: 10s + timeout: 5s + retries: 5 + + oai_spgwu: + image: oai-spgwu-tiny:production + privileged: true + container_name: prod-oai-spgwu-tiny + depends_on: [oai_spgwc] + networks: + public_net: + ipv4_address: 192.168.61.5 + environment: + PID_DIRECTORY: /var/run + INSTANCE: 1 + SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP: eth0 + PGW_INTERFACE_NAME_FOR_SGI: eth0 + SGW_INTERFACE_NAME_FOR_SX: eth0 + SPGWC0_IP_ADDRESS: 192.168.61.4 + NETWORK_UE_IP: '12.1.1.0/24' + NETWORK_UE_NAT_OPTION: 'yes' + healthcheck: + test: /bin/bash -c "pgrep oai_spgwu" + interval: 10s + timeout: 5s + retries: 5 + + flexran_rtc: + image: flexran-rtc:production + privileged: true + container_name: prod-flexran-rtc + networks: + public_net: + ipv4_address: 192.168.61.10 + healthcheck: + test: /bin/bash -c "pgrep rt_controller" + interval: 10s + timeout: 5s + retries: 5 + + trf_gen: + image: trf-gen:production + privileged: true + container_name: prod-trf-gen + networks: + public_net: + ipv4_address: 192.168.61.11 + entrypoint: /bin/bash -c "ip route add 12.1.1.0/24 via 192.168.61.5 dev eth0; sleep infinity" + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.61.5" + interval: 10s + timeout: 5s + retries: 5 + +networks: + private_net: + name: prod-oai-private-net + ipam: + config: + - subnet: 192.168.68.0/26 + public_net: + name: prod-oai-public-net + ipam: + config: + - subnet: 192.168.61.0/26 diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 044a10db93..6967d07c41 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1968,6 +1968,7 @@ set(NR_PDCP_SRC ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c ) set(L2_SRC @@ -2087,6 +2088,7 @@ set (MAC_NR_SRC ${NR_GNB_MAC_DIR}/gNB_scheduler_ulsch.c ${NR_GNB_MAC_DIR}/gNB_scheduler_primitives.c ${NR_GNB_MAC_DIR}/gNB_scheduler_phytest.c + ${NR_GNB_MAC_DIR}/gNB_scheduler_uci.c ${NR_GNB_MAC_DIR}/gNB_scheduler_RA.c ) @@ -3293,7 +3295,7 @@ add_executable(nr_dlsim ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_dlsim - -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN -Wl,--end-group + -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN NGAP_GNB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl ) target_compile_definitions(nr_dlsim PUBLIC -DPHYSICAL_SIMULATOR) @@ -3311,7 +3313,7 @@ add_executable(nr_prachsim ${T_SOURCE} ${SHLIB_LOADER_SOURCES}) target_link_libraries(nr_prachsim - -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN -Wl,--end-group + -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_RU PHY_NR_UE MAC_NR_COMMON SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN NGAP_GNB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl) add_executable(nr_ulschsim @@ -3344,7 +3346,7 @@ add_executable(nr_ulsim ${SHLIB_LOADER_SOURCES} ) target_link_libraries(nr_ulsim - -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN -Wl,--end-group + -Wl,--start-group UTIL SIMU_COMMON SIMU PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON RRC_LIB NR_RRC_LIB CONFIG_LIB L2_LTE_NR L2_NR HASHTABLE X2AP_ENB X2AP_LIB SECU_CN NGAP_GNB -Wl,--end-group m pthread ${ATLAS_LIBRARIES} ${T_LIB} ${ITTI_LIB} dl ) target_compile_definitions(nr_ulsim PUBLIC -DPHYSICAL_SIMULATOR) @@ -3443,7 +3445,7 @@ if (${T_TRACER}) SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX - L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR + L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR NGAP_GNB CN_UTILS GTPV1U NR_GTPV1U SCTP_CLIENT MME_APP UDP LIB_NAS_UE NB_IoT LFDS LFDS7 SIMU_COMMON SIMU SIMU_ETH OPENAIR0_LIB ldpc_orig ldpc_optim ldpc_optim8seg ldpc PROTO_AGENT dfts) if (TARGET ${i}) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 7e43a9d01c..0c31ba8ea6 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1095,7 +1095,10 @@ (Test10: 106 PRBs 50 PDSCH-PRBs MCS Index 16), (Test11: HARQ test 25% TP (4 rounds), (Test12: HARQ test 33% TP (3 rounds), - (Test13: HARQ test 50% TP (2 rounds) + (Test13: HARQ test 50% TP (2 rounds), + (Test14: 3 PTRS, 8 Interpolated Symbols), + (Test15: 6 PTRS, 5 Interpolated Symbols), + (Test16: 11 PTRS, 0 Interpolated Symbols) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1114,8 +1117,11 @@ -n100 -e16 -s10 -n100 -s1 -t25 -n100 -s1 -t33 - -n100 -s1 -t50 - nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11 nr_dlsim.test12 nr_dlsim.test13 + -n100 -s1 -t50 + -n100 -s5 -T 2 2 2 + -n100 -s5 -T 2 1 2 + -n100 -s5 -T 2 0 4 + nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11 nr_dlsim.test12 nr_dlsim.test13 nr_dlsim.test14 nr_dlsim.test15 nr_dlsim.test16 PDSCH test OK segmentation fault|assertion|exiting|fatal 3 @@ -1302,10 +1308,12 @@ execution - nr_prachsim Test cases. (Test1: 106 PRBs - Prach format A2), - (Test2: 217 PRBs - Prach format A2), - (Test3: 273 PRBs - Prach format A2), - (Test4: 106 PRBs - Prach format 0) + nr_prachsim Test cases. (Test1: 30kHz SCS, 106 PRBs, Prach format A2), + (Test2: 30kHz SCS, 217 PRBs, Prach format A2), + (Test3: 30kHz SCS, 273 PRBs, Prach format A2), + (Test4: 30kHz SCS, 106 PRBs, Prach format 0), + (Test5: 120kHz SCS, 32 PRBs, Prach format A2), + (Test6: 120kHz SCS, 66 PRBs, Prach format A2) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1315,8 +1323,10 @@ -a -s -30 -n 100 -p 63 -R 106 -a -s -30 -n 100 -p 63 -R 217 -a -s -30 -n 100 -p 63 -R 273 - -a -s -30 -n 100 -p 63 -R 106 -c 4 - nr_prachsim.test1 nr_prachsim.test2 nr_prachsim.test3 nr_prachsim.test4 + -a -s -30 -n 100 -p 63 -R 106 -c 4 + -a -s -30 -n 100 -p 32 -R 32 -m 3 -c52 + -a -s -30 -n 100 -p 32 -R 66 -m 3 -c52 + nr_prachsim.test1 nr_prachsim.test2 nr_prachsim.test3 nr_prachsim.test4 nr_prachsim.test5 nr_prachsim.test6 PRACH test OK segmentation fault|assertion|exiting|fatal 3 diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index f76eae7f28..674d4a0cac 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -114,6 +114,8 @@ check_supported_distribution() { "rhel7.7") return 0 ;; "rhel7.8") return 0 ;; "rhel8.2") return 0 ;; + "rhel8.3") return 0 ;; + "rhel8.4") return 0 ;; "centos7") return 0 ;; esac return 1 diff --git a/common/utils/msc/msc.h b/common/utils/msc/msc.h index 77ff6fd62f..aab872cfe1 100644 --- a/common/utils/msc/msc.h +++ b/common/utils/msc/msc.h @@ -48,6 +48,7 @@ typedef enum { MSC_MAC_ENB, MSC_RLC_ENB, MSC_PDCP_ENB, + MSC_PDCP_GNB, MSC_RRC_ENB, MSC_RRC_GNB, MSC_IP_ENB, diff --git a/doc/BUILD.md b/doc/BUILD.md index ba5db55cab..bbb06a1e69 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -51,6 +51,19 @@ Calling the `build_oai` script with the -h option gives the list of all availabl # Building PHY Simulators +The PHY layer simulators (LTE and NR) can be built as follows: + +``` +cd /openairinterface5g/ +source oaienv +cd cmake_targets/ +./build_oai -I --phy_simulators +``` + +After completing the build, the binaries are available in the cmake_targets/phy_simulators/build directory. +A copy is also available in the target/bin directory, with all binaries suffixed by the 3GPP release number, today **.Rel15**. + + Detailed information about these simulators can be found [in this dedicated page](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/OpenAirLTEPhySimul) # Building UEs, eNodeB and gNodeB Executables diff --git a/doc/SW_archi.md b/doc/SW_archi.md index dba884dcec..412dad402d 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -70,7 +70,7 @@ if the input is a UE RACH detection * nr_schedule_msg2() {: .func4} * handle_nr_uci() -???? +handles uplink control information, i.e., for the moment HARQ feedback. {: .func4} * handle_nr_ulsch() handles ulsch data prepared by nr_fill_indication() @@ -143,7 +143,8 @@ the samples numbers are the future time for these samples emission on-air {: .func3} # Scheduler -The scheduler is called by the chain: nr_ul_indication()=>gNB_dlsch_ulsch_scheduler() + +The main scheduler function is called by the chain: nr_ul_indication()=>gNB_dlsch_ulsch_scheduler() It calls sub functions to process each physical channel (rach, ...) The scheduler uses and internal map of used RB: vrb_map and vrb_map_UL, so each specific channel scheduler can see the already filled RB in each subframe (the function gNB_dlsch_ulsch_scheduler() clears these two arrays when it starts) @@ -153,16 +154,71 @@ it sends a iiti message to activate the thread for RRC, the answer will be async Calls schedule_nr_mib() that calls mac_rrc_nr_data_req() to fill MIB, -Calls each channel allocation: schedule SI, schedule_ul, schedule_dl, ... -this is a major entry for "phy-test" mode: in this mode, the allocation is fixed -all these channels goes to mac_rrc_nr_data_req() to get the data to transmit +Calls schedule_nr_prach() which schedules the (fixed) PRACH region one frame in +advance. -nr_schedule_ue_spec() is called -* calls nr_simple_dlsch_preprocessor()=> mac_rlc_status_ind() mac_rlc_status_ind() locks and checks directly inside rlc data the quantity of waiting data. So, the scheduler can allocate RBs -* calls nr_update_pucch_scheduling() - * get_pdsch_to_harq_feedback() to schedule retransmission in DL +Calls nr_csi_meas_reporting() to check when to schedule CSI in PUCCH. -Calls nr_fill_nfapi_dl_pdu() to actually populate what should be done by the lower layers to make the Tx subframe +Calls nr_schedule_RA(): checks RA process 0's state. Schedules Msg.2 via +nr_generate_Msg2() if an RA process is ongoing, and pre-allocates the Msg. 3 +for PUSCH as well. + +Calls nr_schedule_ulsch(): It is divided into the "preprocessor" and the +"postprocessor": the first makes the scheduling decisions, the second fills +nFAPI structures to indicate to the PHY what it is supposed to do. To signal +which users have how many resources, the preprocessor populates the +NR_sched_pusch_t (for values changing every TTI, e.g., frequency domain +allocation) and NR_sched_pusch_save_t (for values changing less frequently, at +least in FR1 [to my understanding], e.g., DMRS fields when the time domain +allocation stays between TTIs) structures. Furthermore, the preprocessor is an +exchangeable module that might schedule differently, e.g., one user for +phytest, multiple users in FR1, or maybe FR2: phytest is in +nr_ul_preprocessor_phytest(), for FR1 is nr_simple_ulsch_preprocessor() [under +development], for FR2 does not exist yet. +* calls preprocessor via pre_processor_ul(): the preprocessor is responsible + for allocating CCEs (using allocate_nr_CCEs()). Note that we do not yet have + scheduling requests or buffer status reports, and only one UE. E.g., + nr_simple_ulsch_preprocessor(): + 1) check whether the current frame/slot plus K2 is an UL slot, and return if + not. + 2) Find first free start RB in vrb_map_UL, and as many free consecutive RBs + as possible. + 3) allocate a CCE for the UE (and return if it is not possible) + 4) Calculate DMRS stuff (nr_save_pusch_fields()) and the TBS. + 5) Mark used resources in vrb_map_UL. +* loop through all users: get a free HARQ PID using select_ul_harq_pid() and + update statistics. Fill nFAPI structures directly for PUSCH, and call + config_uldci() and fill_dci_pdu_rel15() for DCI filling and PDCCH messages. + +Calls nr_schedule_ue_spec(). It is divided into the "preprocessor" and the +"postprocessor": the first makes the scheduling decisions, the second fills +nFAPI structures to indicate to the PHY what it is supposed to do. To signal +which users have how many resources, the preprocessor populates the +NR_UE_sched_ctrl_t structure of affected users. In particular, the field rbSize +decides whether a user is to be allocated. Furthermore, the preprocessor is an +exchangeable module that might schedule differently, e.g., one user for +phytest, multiple users in FR1, or maybe FR2: phytest is in +nr_preprocessor_phytest(), for FR1 is nr_simple_dlsch_preprocessor() [under +development], for FR2 does not exist yet. +* calls preprocessor via pre_processor_dl(): the preprocessor is responsible + for allocating CCEs and PUCCH (using allocate_nr_CCEs() and + nr_acknack_scheduling()) and deciding on the frequency/time domain + allocation. E.g., nr_simple_dlsch_preprocessor(): + 1) mac_rlc_status_ind() locks and checks directly inside rlc data the + quantity of waiting data. + 2) return from the preprocessor if there is no data and no timing advance to + send, + 3) otherwise, allocate a CCE for the UE (and return if it is not possible) + 4) find a PUCCH occasion for HARQ + 5a) check if there is a retransmission: if yes, find free resources to + transmit using the same resources, else + 5b) calculate the necessary RBs needed to get a TBS large enough to hold all + data, or until no more resources are available + 6) Mark taken resources in the vrb_map +* loop through all users: check if a new TA is necessary. Then, if a user has + allocated resources, compute its TBS, and fill nFAPI structures + (nr_fill_nfapi_dl_pdu() to populate what should be done by the lower layers + to make the Tx subframe). Update statistics (round, sent bytes). # RRC RRC is a regular thread with itti loop on queue: TASK_RRC_GNB diff --git a/docker/Dockerfile.eNB.rhel8.2 b/docker/Dockerfile.eNB.rhel8.2 index 363b070934..5fcd5a7b9f 100644 --- a/docker/Dockerfile.eNB.rhel8.2 +++ b/docker/Dockerfile.eNB.rhel8.2 @@ -32,6 +32,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --eNB --ninja -w USRP diff --git a/docker/Dockerfile.eNB.rhel8.2.oc4-4 b/docker/Dockerfile.eNB.rhel8.2.oc4-4 index 039183a0f2..5b784c08a2 100644 --- a/docker/Dockerfile.eNB.rhel8.2.oc4-4 +++ b/docker/Dockerfile.eNB.rhel8.2.oc4-4 @@ -33,6 +33,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --eNB --ninja -w USRP diff --git a/docker/Dockerfile.eNB.ubuntu18 b/docker/Dockerfile.eNB.ubuntu18 index 9b6e5cb47d..cdfb37ebfc 100644 --- a/docker/Dockerfile.eNB.ubuntu18 +++ b/docker/Dockerfile.eNB.ubuntu18 @@ -32,9 +32,14 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --eNB --ninja -w USRP +RUN apt-get install -y python3-pip && \ + pip3 install --ignore-installed pyyaml && \ + python3 ./docker/scripts/generateTemplate.py ./docker/scripts/enb_parameters.yaml + # debug #RUN ldconfig -v && ldd /oai-ran/targets/bin/lte-softmodem.Rel15 #RUN ls -ls /oai-ran/targets/bin @@ -73,6 +78,7 @@ RUN apt-get update && \ WORKDIR /opt/oai-enb/bin COPY --from=enb-build /oai-ran/targets/bin/lte-softmodem.Rel15 . +COPY --from=enb-build /oai-ran/docker/scripts/enb_entrypoint.sh entrypoint.sh WORKDIR /usr/local/lib/ COPY --from=enb-build /oai-ran/targets/bin/liboai_eth_transpro.so.Rel15 . @@ -104,21 +110,17 @@ RUN ldconfig # Copy the relevant configuration files for eNB WORKDIR /opt/oai-enb/etc -COPY --from=enb-build /oai-ran/ci-scripts/conf_files/enb.* ./ -COPY --from=enb-build /oai-ran/ci-scripts/conf_files/rcc.* ./ -COPY --from=enb-build /oai-ran/ci-scripts/conf_files/cu.* ./ -COPY --from=enb-build /oai-ran/ci-scripts/conf_files/du.* ./ -COPY --from=enb-build /oai-ran/ci-scripts/conf_files/rru.* ./ +COPY --from=enb-build /oai-ran/docker/etc . WORKDIR /opt/oai-enb -#EXPOSE 2152/udp # S1U, GTP/UDP +# 2152 --> S1U, GTP/UDP +# 36412 --> S1C, SCTP/UDP +# 36422 --> X2C, SCTP/UDP +EXPOSE 2152/udp 36412/udp 36422/udp #EXPOSE 22100/tcp # ? -#EXPOSE 36412/udp # S1C, SCTP/UDP -#EXPOSE 36422/udp # X2C, SCTP/UDP #EXPOSE 50000/udp # IF5 / ORI (control) #EXPOSE 50001/udp # IF5 / ECPRI (data) -#CMD ["/opt/oai-enb/bin/lte-softmodem", "-O", "/opt/oai-enb/etc/enb.conf"] -#ENTRYPOINT ["/opt/oai-enb/bin/entrypoint.sh"] -CMD ["sleep", "infinity"] +ENTRYPOINT ["/opt/oai-enb/bin/entrypoint.sh"] +CMD ["/opt/oai-enb/bin/lte-softmodem.Rel15", "-O", "/opt/oai-enb/etc/enb.conf"] diff --git a/docker/Dockerfile.gNB.rhel8.2 b/docker/Dockerfile.gNB.rhel8.2 index 901df9757c..fb9ade927f 100644 --- a/docker/Dockerfile.gNB.rhel8.2 +++ b/docker/Dockerfile.gNB.rhel8.2 @@ -32,6 +32,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --gNB --ninja -w USRP diff --git a/docker/Dockerfile.gNB.rhel8.2.oc4-4 b/docker/Dockerfile.gNB.rhel8.2.oc4-4 index 197bc2a92a..1e1eba016e 100644 --- a/docker/Dockerfile.gNB.rhel8.2.oc4-4 +++ b/docker/Dockerfile.gNB.rhel8.2.oc4-4 @@ -33,6 +33,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --gNB --ninja -w USRP diff --git a/docker/Dockerfile.gNB.ubuntu18 b/docker/Dockerfile.gNB.ubuntu18 index 4135b0e785..d43ad4709d 100644 --- a/docker/Dockerfile.gNB.ubuntu18 +++ b/docker/Dockerfile.gNB.ubuntu18 @@ -32,6 +32,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --gNB --ninja -w USRP diff --git a/docker/Dockerfile.lteUE.rhel8.2 b/docker/Dockerfile.lteUE.rhel8.2 index 6b64fdec1e..0a853dcd6b 100644 --- a/docker/Dockerfile.lteUE.rhel8.2 +++ b/docker/Dockerfile.lteUE.rhel8.2 @@ -33,6 +33,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --UE --ninja -w USRP diff --git a/docker/Dockerfile.lteUE.rhel8.2.oc4-4 b/docker/Dockerfile.lteUE.rhel8.2.oc4-4 index c390e01e3b..1339d18de6 100644 --- a/docker/Dockerfile.lteUE.rhel8.2.oc4-4 +++ b/docker/Dockerfile.lteUE.rhel8.2.oc4-4 @@ -33,6 +33,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --UE --ninja -w USRP diff --git a/docker/Dockerfile.lteUE.ubuntu18 b/docker/Dockerfile.lteUE.ubuntu18 index f1233d6a01..8793cc54f7 100644 --- a/docker/Dockerfile.lteUE.ubuntu18 +++ b/docker/Dockerfile.lteUE.ubuntu18 @@ -32,6 +32,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --UE --ninja -w USRP diff --git a/docker/Dockerfile.nrUE.rhel8.2 b/docker/Dockerfile.nrUE.rhel8.2 index 466eeedd40..f9f3f8e4bf 100644 --- a/docker/Dockerfile.nrUE.rhel8.2 +++ b/docker/Dockerfile.nrUE.rhel8.2 @@ -32,6 +32,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --nrUE --ninja -w USRP diff --git a/docker/Dockerfile.nrUE.rhel8.2.oc4-4 b/docker/Dockerfile.nrUE.rhel8.2.oc4-4 index 3b09b18b55..d900fff998 100644 --- a/docker/Dockerfile.nrUE.rhel8.2.oc4-4 +++ b/docker/Dockerfile.nrUE.rhel8.2.oc4-4 @@ -33,6 +33,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --nrUE --ninja -w USRP diff --git a/docker/Dockerfile.nrUE.ubuntu18 b/docker/Dockerfile.nrUE.ubuntu18 index eecadacb50..5450194f35 100644 --- a/docker/Dockerfile.nrUE.ubuntu18 +++ b/docker/Dockerfile.nrUE.ubuntu18 @@ -32,6 +32,7 @@ WORKDIR /oai-ran #run build_oai to build the target image RUN /bin/sh oaienv && \ cd cmake_targets && \ + rm -Rf log && \ mkdir -p log && \ ./build_oai --nrUE --ninja -w USRP diff --git a/docker/scripts/enb_entrypoint.sh b/docker/scripts/enb_entrypoint.sh new file mode 100755 index 0000000000..31d99b2a67 --- /dev/null +++ b/docker/scripts/enb_entrypoint.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +set -euo pipefail + +# Based another env var, pick one template to use +if [[ -v USE_FDD_CU ]]; then ln -s /opt/oai-enb/etc/cu.fdd.conf /opt/oai-enb/etc/enb.conf; fi +if [[ -v USE_FDD_DU ]]; then ln -s /opt/oai-enb/etc/du.fdd.conf /opt/oai-enb/etc/enb.conf; fi +if [[ -v USE_FDD_MONO ]]; then ln -s /opt/oai-enb/etc/enb.fdd.conf /opt/oai-enb/etc/enb.conf; fi +if [[ -v USE_TDD_MONO ]]; then ln -s /opt/oai-enb/etc/enb.tdd.conf /opt/oai-enb/etc/enb.conf; fi +if [[ -v USE_FDD_RCC ]]; then ln -s /opt/oai-enb/etc/rcc.if4p5.enb.fdd.conf /opt/oai-enb/etc/enb.conf; fi +if [[ -v USE_FDD_RRU ]]; then ln -s /opt/oai-enb/etc/rru.fdd.conf /opt/oai-enb/etc/enb.conf; fi +if [[ -v USE_TDD_RRU ]]; then ln -s /opt/oai-enb/etc/rru.tdd.conf /opt/oai-enb/etc/enb.conf; fi + +# Only this template will be manipulated +CONFIG_FILES=`ls /opt/oai-enb/etc/enb.conf` + +for c in ${CONFIG_FILES}; do + # grep variable names (format: ${VAR}) from template to be rendered + VARS=$(grep -oP '@[a-zA-Z0-9_]+@' ${c} | sort | uniq | xargs) + + # create sed expressions for substituting each occurrence of ${VAR} + # with the value of the environment variable "VAR" + EXPRESSIONS="" + for v in ${VARS}; do + NEW_VAR=`echo $v | sed -e "s#@##g"` + if [[ "${!NEW_VAR}x" == "x" ]]; then + echo "Error: Environment variable '${NEW_VAR}' is not set." \ + "Config file '$(basename $c)' requires all of $VARS." + exit 1 + fi + EXPRESSIONS="${EXPRESSIONS};s|${v}|${!NEW_VAR}|g" + done + EXPRESSIONS="${EXPRESSIONS#';'}" + + # render template and inline replace config file + sed -i "${EXPRESSIONS}" ${c} +done + +# Load the USRP binaries +if [[ -v USE_B2XX ]]; then + /usr/lib/uhd/utils/uhd_images_downloader.py -t b2xx +elif [[ -v USE_X3XX ]]; then + /usr/lib/uhd/utils/uhd_images_downloader.py -t x3xx +elif [[ -v USE_N3XX ]]; then + /usr/lib/uhd/utils/uhd_images_downloader.py -t n3xx +fi + +echo "==================================" +echo "== Starting eNB soft modem" +if [[ -v USE_ADDITIONAL_OPTIONS ]]; then + echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" + new_args=() + while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift + done + for word in ${USE_ADDITIONAL_OPTIONS}; do + new_args+=("$word") + done + echo "${new_args[@]}" + exec "${new_args[@]}" +else + echo "$@" + exec "$@" +fi diff --git a/docker/scripts/enb_parameters.yaml b/docker/scripts/enb_parameters.yaml new file mode 100644 index 0000000000..a60fc20e29 --- /dev/null +++ b/docker/scripts/enb_parameters.yaml @@ -0,0 +1,248 @@ +#/* +# * 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 +# */ + +--- +- paths: + source_dir: "ci-scripts/conf_files/" + dest_dir: docker/etc + +- configurations: + - filePrefix: cu + outputfilename: "cu.fdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: local_s_if_name + env: "@F1_IF_NAME@" + - key: remote_s_address + env: "@F1_DU_IP_ADDRESS@" + - key: local_s_address + env: "@F1_CU_IP_ADDRESS@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@S1C_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@S1U_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@F1_CU_IP_ADDRESS@" + + - filePrefix: du + outputfilename: "du.fdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: local_n_if_name + env: "@F1_IF_NAME@" + - key: remote_n_address + env: "@F1_DU_IP_ADDRESS@" + - key: local_n_address + env: "@F1_CU_IP_ADDRESS@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + + - filePrefix: rru.fdd + outputfilename: "rru.fdd.conf" + config: + - key: local_if_name + env: "@RRU_IF4P5_IF_NAME@" + - key: remote_address + env: "@RCC_REMOTE_IP_ADDRESS@" + - key: local_address + env: "@RRU_LOCAL_IP_ADDRESS@" + - key: bands + env: "@UTRA_BAND_ID@" + + - filePrefix: rru.tdd + outputfilename: "rru.tdd.conf" + config: + - key: local_if_name + env: "@RRU_IF4P5_IF_NAME@" + - key: remote_address + env: "@RCC_REMOTE_IP_ADDRESS@" + - key: local_address + env: "@RRU_LOCAL_IP_ADDRESS@" + - key: bands + env: "@UTRA_BAND_ID@" + + - filePrefix: enb.band7.tm1.25PRB.usrpb210 + outputfilename: "enb.fdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@ENB_S1C_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@ENB_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@ENB_S1U_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@ENB_S1U_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@ENB_X2_IP_ADDRESS@" + - key: FLEXRAN_ENABLED + env: "@FLEXRAN_ENABLED@" + - key: FLEXRAN_INTERFACE_NAME + env: "@FLEXRAN_INTERFACE_NAME@" + - key: FLEXRAN_IPV4_ADDRESS + env: "@FLEXRAN_IPV4_ADDRESS@" + + - filePrefix: enb.band40.tm1.25PRB.FairScheduler.usrpb210 + outputfilename: "enb.tdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@S1C_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@S1U_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@F1_CU_IP_ADDRESS@" + + - filePrefix: "rcc.band7.tm1.nfapi" + outputfilename: "rcc.if4p5.enb.fdd.conf" + config: + - key: Active_eNBs + env: "@ENB_NAME@" + - key: eNB_name + env: "@ENB_NAME@" + - key: plmn_list + env: + mcc: "@MCC@" + mnc: "@MNC@" + mnc_length: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: local_s_if_name + env: "@F1_IF_NAME@" + - key: remote_s_address + env: "@F1_DU_IP_ADDRESS@" + - key: local_s_address + env: "@F1_CU_IP_ADDRESS@" + - key: eutra_band + env: "@UTRA_BAND_ID@" + - key: downlink_frequency + env: "@DL_FREQUENCY_IN_MHZ@000000" + - key: uplink_frequency_offset + env: "@UL_FREQUENCY_OFFSET_IN_MHZ@000000" + - key: Nid_cell + env: "@NID_CELL@" + - key: N_RB_DL + env: "@NB_PRB@" + - key: ipv4 + env: "@MME_S1C_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1_MME + env: "@S1C_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1_MME + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_INTERFACE_NAME_FOR_S1U + env: "@S1U_IF_NAME@" + - key: ENB_IPV4_ADDRESS_FOR_S1U + env: "@F1_CU_IP_ADDRESS@" + - key: ENB_IPV4_ADDRESS_FOR_X2C + env: "@F1_CU_IP_ADDRESS@" + diff --git a/docker/scripts/generateTemplate.py b/docker/scripts/generateTemplate.py new file mode 100644 index 0000000000..4949e9cf21 --- /dev/null +++ b/docker/scripts/generateTemplate.py @@ -0,0 +1,89 @@ +#/* +# * 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 +# */ +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import re +import yaml +import os +import sys + + +def main(): + #read yaml input parameters + f = open(f'{sys.argv[1]}',) + data = yaml.full_load(f) + dir = os.listdir(f'{data[0]["paths"]["source_dir"]}') + + + #identify configs, read and replace corresponding values + for config in data[1]["configurations"]: + filePrefix = config["filePrefix"] + outputfilename = config["outputfilename"] + for inputfile in dir: + if inputfile.find(filePrefix) >=0: + prefix_outputfile = {"cu": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "du": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "rru.fdd": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "rru.tdd": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "enb.band7.tm1.25PRB.usrpb210": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "enb.band40.tm1.25PRB.FairScheduler.usrpb210": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "rcc.band7.tm1.nfapi": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}' + } + if filePrefix in prefix_outputfile: + outputfile1 = prefix_outputfile[filePrefix] + + directory = f'{data[0]["paths"]["dest_dir"]}' + if not os.path.exists(directory): + os.makedirs(directory, exist_ok=True) + + with open(f'{data[0]["paths"]["source_dir"]}{inputfile}', mode='r') as inputfile, \ + open(outputfile1, mode='w') as outputfile: + for line in inputfile: + count = 0 + for key in config["config"]: + if line.find(key["key"]) >= 0: + count += 1 + if re.search(r'preference', line): + templine = line + elif re.search(r'plmn_list', line): + templine = re.sub(r'[0-9]+', '""', line) + templine = re.sub(r'\"\"', key["env"]["mcc"], templine, 1) + templine = re.sub(r'\"\"', key["env"]["mnc"], templine, 1) + templine = re.sub(r'\"\"', key["env"]["mnc_length"], templine, 1) + elif re.search('downlink_frequency', line): + templine = re.sub(r'[0-9]+', key["env"], line) + elif re.search('uplink_frequency_offset', line): + templine = re.sub(r'[0-9]+', key["env"], line) + + elif re.search(r'"(.*?)"', line): + templine = re.sub(r'(?<=")[^"]*(?=")', key["env"], line) + elif re.search(r'[0-9]', line): + templine = re.sub(r'\d+', key["env"], line) + outputfile.write(templine) + + if count == 0: + outputfile.write(line) + +if __name__ == "__main__": + main() diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index bd4a1a72aa..be9261a117 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -72,6 +72,7 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "UTIL/OPT/opt.h" #include "enb_config.h" +#include "gnb_paramdef.h" #ifndef OPENAIR2 @@ -101,6 +102,7 @@ extern int transmission_mode; extern uint16_t sf_ahead; extern uint16_t sl_ahead; + //pthread_t main_gNB_thread; time_stats_t softmodem_stats_mt; // main thread @@ -870,7 +872,18 @@ void init_gNB_proc(int inst) { gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t)); gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); - char ul_pool[] = "-1,-1"; + int numCPU = sysconf(_SC_NPROCESSORS_ONLN); + uint32_t num_threads_pusch; + paramdef_t PUSCHThreads[] = NUM_THREADS_DESC; + config_get( PUSCHThreads,sizeof(PUSCHThreads)/sizeof(paramdef_t),NULL); + int threadCnt = min(numCPU, num_threads_pusch); + char ul_pool[80]; + sprintf(ul_pool,"-1"); + int s_offset = 0; + for (int icpu=1; icputhreadPool, false); initNotifiedFIFO(gNB->respDecode); } diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 5191551ea3..54f0906e1c 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -416,12 +416,10 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { //printf(">>> nr_ue_pdcch_procedures ended\n"); #endif - if(IS_SOFTMODEM_NOS1){ //&& proc->nr_slot_rx==1 - //Hardcoded rnti value + if(IS_SOFTMODEM_NOS1){ + NR_UE_MAC_INST_t *mac = get_mac_inst(0); protocol_ctxt_t ctxt; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO, - 0x1234, proc->frame_rx, - proc->nr_slot_rx, 0); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO, mac->crnti, proc->frame_rx, proc->nr_slot_rx, 0); pdcp_run(&ctxt); } } diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index feb020154b..f8e9b0959f 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -70,7 +70,7 @@ extern "C" #define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n" #define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" #define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" - +#define CONFIG_HLP_256QAM "Use the 256 QAM mcs table for PDSCH\n" //#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation" #define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" @@ -109,6 +109,7 @@ extern "C" #define TIMING_SOURCE softmodem_params.timing_source #define SEND_DMRSSYNC softmodem_params.send_dmrs_sync #define USIM_TEST softmodem_params.usim_test +#define USE_256QAM_TABLE softmodem_params.use_256qam_table #define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat"; @@ -137,6 +138,7 @@ extern "C" {"basicsim", CONFIG_HLP_RFSIM, PARAMFLAG_BOOL, uptr:&basicsim, defintval:0, TYPE_INT, 0}, \ {"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \ {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \ + {"use-256qam-table", CONFIG_HLP_256QAM, PARAMFLAG_BOOL, iptr:&USE_256QAM_TABLE, defintval:0, TYPE_INT, 0}, \ } @@ -222,6 +224,7 @@ typedef struct { uint32_t timing_source; int hw_timing_advance; uint32_t send_dmrs_sync; + int use_256qam_table; } softmodem_params_t; extern uint64_t get_softmodem_optmask(void); 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 87a4d6f6af..da84901602 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 @@ -472,6 +472,21 @@ typedef struct { uint8_t cbgti; uint8_t codeBlockGroupFlushIndicator; // to be check the fields needed to L1 with NR_DL_UE_HARQ_t and NR_UE_DLSCH_t + // PTRS [TS38.214, sec 5.1.6.3] + /// PT-RS antenna ports [TS38.214, sec 5.1.6.3] [TS38.211, table 7.4.1.2.2-1] Bitmap occupying the 6 LSBs with: bit 0: antenna port 1000 bit 5: antenna port 1005 and for each bit 0: PTRS port not used 1: PTRS port used + uint8_t PTRSPortIndex ; + /// PT-RS time density [TS38.214, table 5.1.6.3-1] 0: 1 1: 2 2: 4 + uint8_t PTRSTimeDensity; + /// PT-RS frequency density [TS38.214, table 5.1.6.3-2] 0: 2 1: 4 + uint8_t PTRSFreqDensity; + /// PT-RS resource element offset [TS38.211, table 7.4.1.2.2-1] Value: 0->3 + uint8_t PTRSReOffset; + /// PT-RS-to-PDSCH EPRE ratio [TS38.214, table 4.1-2] Value :0->3 + uint8_t nEpreRatioOfPDSCHToPTRS; + /// MCS table for this DLSCH + uint8_t mcs_table; + + uint16_t pduBitmap; } fapi_nr_dl_config_dlsch_pdu_rel15_t; typedef struct { @@ -783,7 +798,7 @@ typedef struct { } fapi_nr_pusch_power_control_t; typedef enum {tx_config_codebook = 1, tx_config_nonCodebook = 2} tx_config_t; -typedef enum {transform_precoder_disabled = 0, transform_precoder_enabled = 1} transform_precoder_t; +typedef enum {transform_precoder_enabled = 0, transform_precoder_disabled = 1} transform_precoder_t; typedef enum { codebook_subset_fullyAndPartialAndNonCoherent = 1, codebook_subset_partialAndNonCoherent = 2, diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c index efa5abdc90..1afe82497a 100644 --- a/openair1/PHY/CODING/nr_rate_matching.c +++ b/openair1/PHY/CODING/nr_rate_matching.c @@ -347,13 +347,13 @@ void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f) } break; case 8: - e1=e+(E/6); - e2=e1+(E/6); - e3=e2+(E/6); - e4=e3+(E/6); - e5=e4+(E/6); - e6=e5+(E/6); - e7=e6+(E/6); + e1=e+(E/8); + e2=e1+(E/8); + e3=e2+(E/8); + e4=e3+(E/8); + e5=e4+(E/8); + e6=e5+(E/8); + e7=e6+(E/8); for (int j = 0,j2=0; j< E/8; j++,j2+=8){ e[j] = f[j2]; e1[j] = f[j2+1]; @@ -407,8 +407,16 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm, #ifdef RM_DEBUG printf("nr_rate_matching_ldpc: E %d, F %d, Foffset %d, k0 %d, Ncb %d, rvidx %d\n", E, F, Foffset,ind, Ncb, rvidx); #endif - AssertFatal(Foffset <= E,"Foffset %d > E %d\n",Foffset,E); - AssertFatal(Foffset <= Ncb,"Foffset %d > Ncb %d\n",Foffset,Ncb); + AssertFatal(Foffset <= E, + "Foffset %d > E %d " + "(Ilbrm %d, Tbslbrm %d, Z %d, BG %d, C %d)\n", + Foffset, E, + Ilbrm, Tbslbrm, Z, BG, C); + AssertFatal(Foffset <= Ncb, + "Foffset %d > Ncb %d " + "(Ilbrm %d, Tbslbrm %d, Z %d, BG %d, C %d)\n", + Foffset, Ncb, + Ilbrm, Tbslbrm, Z, BG, C); if (ind >= Foffset && ind < (F+Foffset)) ind = F+Foffset; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 80469f3e81..49ec60c94b 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -431,11 +431,18 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, //gNB_config->subframe_config.dl_cyclic_prefix_type.value = (fp->Ncp == NORMAL) ? NFAPI_CP_NORMAL : NFAPI_CP_EXTENDED; gNB->mac_enabled = 1; - fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); - fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); - fp->nr_band = 78; -// fp->threequarter_fs= 0; - + if (mu==1) { + fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->nr_band = 78; + // fp->threequarter_fs= 0; + } else if (mu==3) { + fp->dl_CarrierFreq = 27524520000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value); + fp->ul_CarrierFreq = 27524520000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000); + fp->nr_band = 261; + // fp->threequarter_fs= 0; + } + gNB_config->carrier_config.dl_bandwidth.value = config_bandwidth(mu, N_RB_DL, fp->nr_band); nr_init_frame_parms(gNB_config, fp); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 24e41d7bfb..abc504d6e3 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -393,6 +393,10 @@ void phy_init_nr_ue__PDSCH(NR_UE_PDSCH *const pdsch, //pdsch->dl_ch_rho2_ext = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) ); pdsch->dl_ch_mag0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); pdsch->dl_ch_magb0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + pdsch->dl_ch_magr0 = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + pdsch->ptrs_phase_per_slot = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + pdsch->ptrs_re_per_slot = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); + pdsch->dl_ch_ptrs_estimates_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) ); // the allocated memory size is fixed: AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" ); @@ -413,6 +417,10 @@ void phy_init_nr_ue__PDSCH(NR_UE_PDSCH *const pdsch, //pdsch->dl_ch_rho2_ext[idx] = (int32_t*)malloc16_clear( sizeof(int32_t) * num ); pdsch->dl_ch_mag0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); pdsch->dl_ch_magb0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); + pdsch->dl_ch_magr0[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * num ); + pdsch->ptrs_re_per_slot[idx] = (int32_t *)malloc16_clear(sizeof(int32_t) * 14); + pdsch->ptrs_phase_per_slot[idx] = (int32_t *)malloc16_clear( sizeof(int32_t) * 14 ); + pdsch->dl_ch_ptrs_estimates_ext[idx]= (int32_t *)malloc16_clear( sizeof(int32_t) * num); } } } diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 171980d343..ba4147e5cd 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -41,38 +41,32 @@ int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp) int case_E[8] = {8, 12, 16, 20, 32, 36, 40, 44}; switch(mu) { - - case NR_MU_0: // case A - n = i_ssb >> 1; - symbol = case_AC[i_ssb % 2] + 14*n; - break; - - case NR_MU_1: - if (type == 1){ // case B - n = i_ssb >> 2; - symbol = case_BD[i_ssb % 4] + 28*n; - } - if (type == 2){ // case C - n = i_ssb >> 1; - symbol = case_AC[i_ssb % 2] + 14*n; - } - break; - - case NR_MU_3: // case D - n_temp = i_ssb >> 2; - n = n_temp + (n_temp >> 2); - symbol = case_BD[i_ssb % 4] + 28*n; - break; - - case NR_MU_4: // case E - n_temp = i_ssb >> 3; - n = n_temp + (n_temp >> 2); - symbol = case_E[i_ssb % 8] + 56*n; - break; - - - default: - AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu); + case NR_MU_0: // case A + n = i_ssb >> 1; + symbol = case_AC[i_ssb % 2] + 14*n; + break; + case NR_MU_1: + if (type == 1){ // case B + n = i_ssb >> 2; + symbol = case_BD[i_ssb % 4] + 28*n; + } + if (type == 2){ // case C + n = i_ssb >> 1; + symbol = case_AC[i_ssb % 2] + 14*n; + } + break; + case NR_MU_3: // case D + n_temp = i_ssb >> 2; + n = n_temp + (n_temp >> 2); + symbol = case_BD[i_ssb % 4] + 28*n; + break; + case NR_MU_4: // case E + n_temp = i_ssb >> 3; + n = n_temp + (n_temp >> 2); + symbol = case_E[i_ssb % 8] + 56*n; + break; + default: + AssertFatal(0==1, "Invalid numerology index %d for the synchronization block\n", mu); } if (half_frame_index) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c index a881773910..2d79158920 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c @@ -47,6 +47,7 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *eNB, uint32_t rb; int32_t *ul_ch; int32_t n0_power_tot; + int64_t n0_power_tot2; int len; int offset; // noise measurements @@ -75,43 +76,47 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *eNB, } + n0_power_tot2=0; + int nb_rb=0; for (rb=0; rbN_RB_UL; rb++) { - n0_power_tot=0; + n0_power_tot=0; + int offset0= (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; + if ((rb_mask[rb>>5]&(1<<(rb&31))) == 0) { // check that rb was not used in this subframe + nb_rb++; for (aarx=0; aarxnb_antennas_rx; aarx++) { - + measurements->n0_subband_power[aarx][rb] = 0; + for (int s=0;s<14-(frame_parms->Ncp<<1);s++) { // select the 7th symbol in an uplink subframe - offset = (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; - offset += (7*frame_parms->ofdm_symbol_size); - ul_ch = &common_vars->rxdataF[aarx][offset]; - len = 12; + offset = offset0 + (s*frame_parms->ofdm_symbol_size); + ul_ch = &common_vars->rxdataF[aarx][offset]; + len = 12; // just do first half of middle PRB for odd number of PRBs - if (((frame_parms->N_RB_UL&1) == 1) && - (rb==(frame_parms->N_RB_UL>>1))) { - len=6; - } - if (clear == 1) - measurements->n0_subband_power[aarx][rb]=0; + if (((frame_parms->N_RB_UL&1) == 1) && + (rb==(frame_parms->N_RB_UL>>1))) { + len=6; + } - AssertFatal(ul_ch, "RX signal buffer (freq) problem"); + AssertFatal(ul_ch, "RX signal buffer (freq) problem"); - measurements->n0_subband_power[aarx][rb] = signal_energy_nodc(ul_ch,len); - //((k1*(signal_energy_nodc(ul_ch,len))) - // + (k2*measurements->n0_subband_power[aarx][rb])); + measurements->n0_subband_power[aarx][rb] += signal_energy_nodc(ul_ch,len); - measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(measurements->n0_subband_power[aarx][rb]); - // printf("subframe %d (%d): eNB %d, aarx %d, rb %d len %d: energy %d (%d dB)\n",subframe,offset,eNB_id,aarx,rb,len,signal_energy_nodc(ul_ch,len), - // measurements->n0_subband_power_dB[aarx][rb]); - n0_power_tot += measurements->n0_subband_power[aarx][rb]; + } + measurements->n0_subband_power[aarx][rb]/=(14-(frame_parms->Ncp<<1)); + measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(measurements->n0_subband_power[aarx][rb]); + n0_power_tot += measurements->n0_subband_power[aarx][rb]; + } - - measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_power_tot); + n0_power_tot/=frame_parms->nb_antennas_rx; + n0_power_tot2 += n0_power_tot; + measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_power_tot/frame_parms->nb_antennas_rx); measurements->n0_subband_power_tot_dBm[rb] = measurements->n0_subband_power_tot_dB[rb] - eNB->rx_total_gain_dB - dB_fixed(frame_parms->N_RB_UL); } } + if (nb_rb>0) measurements->n0_subband_power_avg_dB = dB_fixed(n0_power_tot2/nb_rb); } void lte_eNB_srs_measurements(PHY_VARS_eNB *eNB, diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 1e0dd9db1b..f39f3ef872 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -1070,6 +1070,8 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 ); if (packet_type == IF5_RRH_GW_DL) { if (eth->compression == ALAW_COMPRESS) { + AssertFatal(1==0,"IF5 compression needs reworking\n"); +/* if (eth->flags == ETH_RAW_MODE) { data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); } else { @@ -1100,28 +1102,31 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 0 ); } +*/ } else if (eth->compression == NO_COMPRESS) { - for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] = (void*)&ru->common.txdata[i][subframe*fp->samples_per_tti]; + for (i=0; i < ru->nb_tx; i++) + txp[i] = (int32_t*)&ru->common.txdata[i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 1 ); - clock_gettime( CLOCK_MONOTONIC, &start_comp); - ru->ifdevice.trx_write_func(&ru->ifdevice, - (proc_timestamp + packet_id*spp_eth), - (void**)txp, - spp_eth, - fp->nb_antennas_tx, - 0); - clock_gettime( CLOCK_MONOTONIC, &end_comp); - LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 0 ); - for (i=0; i < fp->nb_antennas_tx; i++) - txp[i] += spp_eth; + for (int aid=0; aidnb_tx;aid++) { + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 1 ); + clock_gettime( CLOCK_MONOTONIC, &start_comp); + ru->ifdevice.trx_write_func2(&ru->ifdevice, + (proc_timestamp + packet_id*spp_eth-500)*(30720/spsf), + (void*)txp[aid], + spp_eth, + aid, + 0); + LOG_D(HW,"SF %d : packet %d, TS %llu\n",subframe,packet_id,(unsigned long long)(proc_timestamp+packet_id*spp_eth)); + clock_gettime( CLOCK_MONOTONIC, &end_comp); + LOG_D(HW,"[SF %d] IF_Write_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 0 ); + txp[aid] += spp_eth; - } + } + } } } else if (packet_type == IF5_RRH_GW_UL) { if (eth->compression == ALAW_COMPRESS) { @@ -1131,8 +1136,8 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES); } for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 ); + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 1 ); clock_gettime( CLOCK_MONOTONIC, &start_comp); for (i=0; i < fp->nb_antennas_rx; i++) { for (element_id=0; element_id< spp_eth; element_id++){ @@ -1142,8 +1147,8 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t } clock_gettime( CLOCK_MONOTONIC, &end_comp); LOG_D(HW,"[SF %d] Compress_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_comp, end_comp)); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 1 ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF, 0 ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 1 ); clock_gettime( CLOCK_MONOTONIC, &start_comp); ru->ifdevice.trx_write_func(&ru->ifdevice, (proc_timestamp + packet_id*spp_eth), @@ -1310,9 +1315,9 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp=ru->frame_parms; - int32_t *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; + int32_t *txp[ru->nb_tx], *rxp[ru->nb_rx]; - uint16_t packet_id=0, i=0, element_id=0; + uint16_t packet_id=0, i=0; #ifdef DEBUG_UL_MOBIPASS //int8_t dummy_buffer_rx[fp->samples_per_tti*2]; uint8_t rxe; @@ -1321,11 +1326,12 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 int32_t spp_eth = (int32_t) ru->ifdevice.openair0_cfg->samples_per_packet; int32_t spsf = (int32_t) ru->ifdevice.openair0_cfg->samples_per_frame/10; - void *alaw_buffer = ru->ifbuffer.rx; - uint16_t *data_block = NULL; - uint16_t *j = NULL; - openair0_timestamp timestamp[spsf / spp_eth]; + openair0_timestamp timestamp[ru->nb_rx*spsf / spp_eth]; + long timein[ru->nb_rx*spsf/spp_eth]; + long timeout[ru->nb_rx*spsf/spp_eth]; + struct timespec if_time; + memset(timestamp, 0, sizeof(timestamp)); eth_state_t *eth = (eth_state_t*) (ru->ifdevice.priv); @@ -1333,6 +1339,9 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 if (packet_type == IF5_RRH_GW_DL) { if (eth->compression == ALAW_COMPRESS) { + AssertFatal(1==0,"IF5 compression needs reworking\n"); + +/* if (eth->flags == ETH_RAW_MODE) { data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); } else { @@ -1364,13 +1373,14 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 LOG_D(HW,"[SF %d] Decomperss_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); } +*/ } else if (eth->compression == NO_COMPRESS) { for (i=0; i < fp->nb_antennas_tx; i++) txp[i] = (void*)&ru->common.txdata[i][subframe*fp->samples_per_tti]; for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF5_PKT_ID, packet_id ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 1 ); + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RECV_IF5_PKT_ID, packet_id ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 1 ); clock_gettime( CLOCK_MONOTONIC, &start_decomp); ru->ifdevice.trx_read_func(&ru->ifdevice, ×tamp[packet_id], @@ -1379,7 +1389,7 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 fp->nb_antennas_tx); clock_gettime( CLOCK_MONOTONIC, &end_decomp); LOG_D(HW,"[SF %d] IF_Read_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 0 ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 0 ); for (i=0; i < fp->nb_antennas_tx; i++) txp[i] += spp_eth; @@ -1389,6 +1399,8 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 } else if (packet_type == IF5_RRH_GW_UL) { if (eth->compression == ALAW_COMPRESS) { + AssertFatal(1==0,"IF5 compression needs reworking\n"); +/* if (eth->flags == ETH_RAW_MODE) { data_block = (uint16_t*)(alaw_buffer + APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES); } else { @@ -1419,197 +1431,55 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 LOG_D(HW,"[SF %d] Decomperss_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF, 0 ); } +*/ } else if (eth->compression == NO_COMPRESS) { - for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] = (void*)&ru->common.rxdata[i][subframe*fp->samples_per_tti]; - - for (packet_id=0; packet_id < spsf / spp_eth; packet_id++) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 1 ); - clock_gettime( CLOCK_MONOTONIC, &start_decomp); - ru->ifdevice.trx_read_func(&ru->ifdevice, + int16_t temp_rx[spp_eth*2] __attribute__((aligned(32))); + for (i=0; i < ru->nb_rx; i++) + rxp[i] = &ru->common.rxdata[i][subframe*fp->samples_per_tti]; + int aid; + int firstTS=1; + openair0_timestamp oldTS=0; + + for (packet_id=0; packet_id < ru->nb_rx*spsf / spp_eth; packet_id++) { + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SEND_IF5_PKT_ID, packet_id ); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 1 ); + clock_gettime( CLOCK_MONOTONIC, &if_time); + timein[packet_id] = if_time.tv_nsec; + ru->ifdevice.trx_read_func2(&ru->ifdevice, ×tamp[packet_id], - (void**)rxp, + (void*)temp_rx, spp_eth, - fp->nb_antennas_rx); + &aid); + clock_gettime( CLOCK_MONOTONIC, &if_time); + timeout[packet_id] = if_time.tv_nsec; + timestamp[packet_id] /= (30720/spsf); + LOG_D(PHY,"subframe %d: Received packet %d: aid %d, TS %llu, oldTS %llu, diff %lld, \n",subframe,packet_id,aid,(unsigned long long)timestamp[packet_id],(unsigned long long)oldTS,(unsigned long long)(timestamp[packet_id]-timestamp[0])); + if (aid==0) { + if (firstTS==1) firstTS=0; + else if (oldTS + 256 != timestamp[packet_id]) { + LOG_I(PHY,"oldTS %llu, newTS %llu, diff %llu, timein %lu, timeout %lu\n",(long long unsigned int)oldTS,(long long unsigned int)timestamp[packet_id],(long long unsigned int)timestamp[packet_id]-oldTS,timein[packet_id],timeout[packet_id]); + for (int i=0;i<=packet_id;i++) LOG_I(PHY,"packet %d TS %llu, timein %lu, timeout %lu\n",i,(long long unsigned int)timestamp[i],timein[i],timeout[i]); + AssertFatal(1==0,"fronthaul problem\n"); + } + + oldTS = timestamp[packet_id]; + } + + + // HYPOTHESIS: first packet per subframe has lowest timestamp of subframe + // should detect out of order and act accordingly .... + AssertFatal(aid==0 || aid==1,"aid %d != 0 or 1\n",aid); + //LOG_I(PHY,"rxp[%d] %p, dest %p, offset %d (%lld,%lld)\n",aid,rxp[aid],rxp[aid]+(timestamp[packet_id]-timestamp[0]),(timestamp[packet_id]-timestamp[0]),timestamp[packet_id],timestamp[0]); + memcpy((void*)(rxp[aid]+(timestamp[packet_id]-timestamp[0])), + (void*)temp_rx, + spp_eth<<2); clock_gettime( CLOCK_MONOTONIC, &end_decomp); LOG_D(HW,"[SF %d] IF_Read_Time: %"PRId64"\n",subframe,clock_difftime_ns(start_decomp, end_decomp)); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 0 ); - for (i=0; i < fp->nb_antennas_rx; i++) - rxp[i] += spp_eth; + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_IF0, 0 ); } } *proc_timestamp = timestamp[0]; - - } else if (packet_type == IF5_MOBIPASS) { - if (ru->if_timing == synch_to_mobipass_standalone) { - uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES; - openair0_timestamp timestamp_mobipass[fp->samples_per_tti/db_fulllength]; - int32_t *rx_buffer=NULL; - __m128i *data_block=NULL, *data_block_head=NULL; - __m128i *rxp128; - __m128i r0; - - unsigned char _rx_buffer[MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)]; - rx_buffer = (int32_t *)_rx_buffer; - data_block_head = (__m128i *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t); - - rxp[0] = (void*)&ru->common.rxdata[0][subframe*ru->frame_parms->samples_per_tti]; - rxp128 = (__m128i *) (rxp[0]); - - packet_id=0; - while(packet_idsamples_per_tti/db_fulllength) { - data_block = data_block_head; - - ru->ifdevice.trx_read_func(&ru->ifdevice, - ×tamp_mobipass[packet_id], - (void**)&rx_buffer, - db_fulllength, - 1 - ); - - //store rxdata and increase packet_id - rxp[0] = (void*)&ru->common.rxdata[0][(subframe*ru->frame_parms->samples_per_tti)+packet_id*db_fulllength]; - rxp128 = (__m128i *) (rxp[0]); - for (i=0; i>2; i+=2) { - r0 = _mm_loadu_si128(data_block++); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4); - } - packet_id++; - }//end while - - *proc_timestamp = ntohl(timestamp_mobipass[0]); - } else { - - uint16_t db_fulllength = PAYLOAD_MOBIPASS_NUM_SAMPLES; - openair0_timestamp timestamp_mobipass[fp->samples_per_tti/db_fulllength]; -#ifdef DEBUG_UL_MOBIPASS - int lower_offset = 0; - int upper_offset = 70000; -#endif - int subframe_skip = 0; - int reset_flag = 0; - int32_t *rx_buffer=NULL; - __m128i *data_block=NULL, *data_block_head=NULL; - __m128i *rxp128; - __m128i r0; - - //rx_buffer = memalign(16, MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); - rx_buffer = malloc(MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + db_fulllength*sizeof(int16_t)); - IF5_mobipass_header_t *header = (IF5_mobipass_header_t *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES); - data_block_head = (__m128i *)((uint8_t *)rx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t); - - rxp[0] = (void*)&ru->common.rxdata[0][subframe*ru->frame_parms->samples_per_tti]; - rxp128 = (__m128i *) (rxp[0]); - - RU_proc_t *proc = &ru->proc; -/* - // while(packet_idsamples_per_tti/db_fulllength) { - data_block = data_block_head; - - eNB->ifdevice.trx_read_func(&eNB->ifdevice, - &ts0, - (void**)&rx_buffer, - db_fulllength, - 1 - ); - - if ((header->seqno == 1)&&(first_packet==1)) { - first_packet = 0; //ignore the packets before synchnorization - packet_id = 0; - ts_offset = ntohl(ts0); - } - if (first_packet==0) { - packet_cnt++; - ts = ntohl(ts0); - packet_id = (ts-ts_offset)/db_fulllength; - packet_id = packet_id % (fp->samples_per_tti/db_fulllength); - - printf("[IF5_tools]packet_id:%d\n", packet_id); - // if (ts_stored == 0) { - // ts_stored = 1; - *proc_timestamp = ntohl(ts - (packet_id*db_fulllength)); - // } - rxp[0] = (void*)&eNB->common_vars.rxdata[0][0][(subframe*eNB->frame_parms.samples_per_tti)+packet_id*db_fulllength]; - rxp128 = (__m128i *) (rxp[0]); - - for (i=0; i>2; i+=2) { - r0 = _mm_loadu_si128(data_block++); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4); - } - } - // }//end while -*/ - - - packet_id=0; - while(packet_idsamples_per_tti/db_fulllength) { - data_block = data_block_head; - - - ru->ifdevice.trx_read_func(&ru->ifdevice, - ×tamp_mobipass[packet_id], - (void**)&rx_buffer, - db_fulllength, - 1 - ); -#ifdef DEBUG_UL_MOBIPASS - if (((proc->timestamp_tx + lower_offset) > ntohl(timestamp_mobipass[packet_id])) || ((proc->timestamp_tx + upper_offset) < ntohl(timestamp_mobipass[packet_id]))) { - //ignore the packet - subframe_skip_extra = (subframe_skip_extra + 1)%67; - LOG_D("[Mobipass] ignored packet, id:[%d,%d], proc->timestamp_tx:%llu, proc->timestamp_rx:%llu, seqno:%d\n", packet_id,subframe_skip_extra, proc->timestamp_tx, ntohl(timestamp_mobipass[packet_id]), header->seqno); - } -#endif - //skip SUBFRAME_SKIP_NUM_MOBIPASS additional UL packets - if ((start_flag == 1) && (subframe_skip < SUBFRAME_SKIP_NUM_MOBIPASS)){ - subframe_skip++; - offset_cnt = header->seqno; - } else { - if ((offset_cnt != header->seqno) && (start_flag == 0) && (proc->first_rx > 3)){ -#ifdef DEBUG_UL_MOBIPASS - LOG_D(PHY,"[Mobipass] Reset sequence number, offset_cnt:%d, header->seqno:%d, packet_id:%d\n", offset_cnt, header->seqno, packet_id); -#endif - reset_flag=1; - } - if ((reset_flag == 1) && (proc->first_rx > 3 ) && (start_flag == 0) && (packet_id == 0)) { - packet_id = 1; - reset_flag = 0; - } - start_flag = 0; - - //store rxdata and increase packet_id - rxp[0] = (void*)&ru->common.rxdata[0][(subframe*ru->frame_parms->samples_per_tti)+packet_id*db_fulllength]; - rxp128 = (__m128i *) (rxp[0]); - for (i=0; i>2; i+=2) { - r0 = _mm_loadu_si128(data_block++); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpacklo_epi8(r0,r0),8),4); - *rxp128++ =_mm_slli_epi16(_mm_srai_epi16(_mm_unpackhi_epi8(r0,r0),8),4); - } - packet_id++; - offset_cnt = (header->seqno+1)&255; - } - }//end while - - *proc_timestamp = ntohl(timestamp_mobipass[0]); -#ifdef DEBUG_UL_MOBIPASS - LOG_I(PHY,"[Mobipass][Recv_MOBIPASS] timestamp: %llu\n ", *proc_timestamp); - if (eNB->CC_id>0) { - rxe = dB_fixed(signal_energy(rxp[0],fp->samples_per_tti)); - if (rxe > 0){ - LOG_I(PHY,"[Mobipass] frame:%d, subframe:%d, energy %d\n", (*proc_timestamp/(10*fp->samples_per_tti))&1023,subframe, rxe); - - // LOG_M("rxsigmb.m","rxs",(void*)dummy_buffer_rx, fp->samples_per_tti,1, 5); - // exit(-1); - } - } -#endif - free(rx_buffer); - - - } } else { AssertFatal(1==0, "recv_IF5 - Unknown packet_type %x", packet_type); } diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index d3ed2ed439..31e97741fd 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -89,7 +89,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, int32_t *prach_ifft=(int32_t *)NULL; int32_t **prach_ifftp=(int32_t **)NULL; int prach_ifft_cnt=0; - + int exit_flag=0; LTE_DL_FRAME_PARMS *fp; int nb_rx; if(eNB) { @@ -177,32 +177,33 @@ void rx_prach0(PHY_VARS_eNB *eNB, } AssertFatal(ru!=NULL,"ru is null\n"); - + int8_t dBEn0=0; for (aa=0; aaif_south == LOCAL_RF) { // set the time-domain signal if we have to use it in this node + if (ru->if_south == LOCAL_RF || ru->function == NGFI_RAU_IF5) { // set the time-domain signal if we have to use it in this node // DJP - indexing below in subframe zero takes us off the beginning of the array??? prach[aa] = (int16_t *)&ru->common.rxdata[aa][(subframe*fp->samples_per_tti)-ru->N_TA_offset]; if (LOG_DUMPFLAG(PRACH)) { int32_t en0=signal_energy((int32_t *)prach[aa],fp->samples_per_tti); - int8_t dbEn0 = dB_fixed(en0); - int8_t rach_dBm = dbEn0 - ru->rx_total_gain_dB; + dBEn0 = dB_fixed(en0); + int8_t rach_dBm = dBEn0 - ru->rx_total_gain_dB; char buffer[80]; - if (dbEn0>32 && prach[0]!= NULL) { + if (dBEn0>30 && prach[0]!= NULL) { static int counter=0; - sprintf(buffer, "%s%d", "/tmp/prach_rx",counter); - LOG_M(buffer,"prach_rx",prach[0],fp->samples_per_tti,1,13); + sprintf(buffer, "%s%d", "/tmp/prach_rx.m",counter); + LOG_M(buffer,"prach_rx",prach[0],fp->samples_per_tti,1,1); + exit_flag=1; } - if (dB_fixed(en0)>32) { + if (dBEn0>30) { sprintf(buffer, "rach_dBm:%d",rach_dBm); - if (prach[0]!= NULL) LOG_M("prach_rx","prach_rx",prach[0],fp->samples_per_tti,1,1); + if (prach[0]!= NULL) LOG_M("prach_rx.m","prach_rx",prach[0],fp->samples_per_tti,1,1); LOG_I(PHY,"RU %d, br_flag %d ce_level %d frame %d subframe %d per_tti:%d prach:%p (energy %d) TA:%d %s rxdata:%p index:%d\n", ru->idx,br_flag,ce_level,frame_prach,subframe,fp->samples_per_tti, - prach[aa],dbEn0,ru->N_TA_offset,buffer,ru->common.rxdata[aa], + prach[aa],dBEn0,ru->N_TA_offset,buffer,ru->common.rxdata[aa], (subframe*fp->samples_per_tti)-ru->N_TA_offset); } } @@ -415,7 +416,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if ( LOG_DEBUGFLAG(PRACH)) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if ((en > 60)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,frame_prach,subframe,en); + if ((en > 10)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,frame_prach,subframe,en); } } @@ -454,9 +455,9 @@ void rx_prach0(PHY_VARS_eNB *eNB, for (preamble_index=0 ; preamble_index<64 ; preamble_index++) { if (LOG_DEBUGFLAG(PRACH)) { - int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); + // int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",frame_prach,subframe,preamble_index,br_flag); + if (dBEn0>30) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",frame_prach,subframe,preamble_index,br_flag); } if (restricted_set == 0) { @@ -539,10 +540,10 @@ void rx_prach0(PHY_VARS_eNB *eNB, // Compute DFT of RX signal (conjugate input, results in conjugate output) for each new rootSequenceIndex if (LOG_DEBUGFLAG(PRACH)) { - int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); + //en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) LOG_I(PHY,"frame %d, subframe %d : preamble index %d: offset %d, preamble shift %d (br_flag %d, en %d)\n", - frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,en); + if (dBEn0>30) LOG_I(PHY,"frame %d, subframe %d : preamble index %d: offset %d, preamble shift %d (br_flag %d, en %d)\n", + frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,dBEn0); } log2_ifft_size = 10; @@ -564,13 +565,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, memset(prachF, 0, sizeof(int16_t)*2*1024 ); - if (LOG_DUMPFLAG(PRACH)) { + if (LOG_DUMPFLAG(PRACH)) { if (prach[0]!= NULL) LOG_M("prach_rx0.m","prach_rx0",prach[0],6144+792,1,1); LOG_M("prach_rx1.m","prach_rx1",prach[1],6144+792,1,1); LOG_M("prach_rxF0.m","prach_rxF0",rxsigF[0],12288,1,1); LOG_M("prach_rxF1.m","prach_rxF1",rxsigF[1],12288,1,1); - } + } for (aa=0; aa60) && (br_flag==1)) + if (dBEn0>30) LOG_D(PHY,"frame %d, subframe %d : max_preamble_energy %d, max_preamble_delay %d, max_preamble %d (br_flag %d,ce_level %d, levdB %d, lev %d)\n", frame_prach,subframe, *max_preamble_energy,*max_preamble_delay, @@ -648,10 +649,10 @@ void rx_prach0(PHY_VARS_eNB *eNB, *avg_preamble_energy=dB_fixed(avg_en/64); - if (LOG_DUMPFLAG(PRACH)) { + if (exit_flag==1) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) { + if (en>30) { k = (12*n_ra_prb) - 6*fp->N_RB_UL; if (k<0) k+=fp->ofdm_symbol_size; @@ -665,19 +666,20 @@ void rx_prach0(PHY_VARS_eNB *eNB, 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); - exit(-1); + LOG_M("SF2_3.m","sf2_3",&ru->common.rxdata[0][2*fp->samples_per_tti],2*fp->samples_per_tti,1,1); } else { LOG_E(PHY,"Dumping prach (br_flag %d), k = %d (n_ra_prb %d)\n",br_flag,k,n_ra_prb); LOG_M("rxsigF_br.m","prach_rxF_br",&rxsigF[0][0],12288,1,1); LOG_M("prach_rxF_comp0_br.m","prach_rxF_comp0_br",prachF,1024,1,1); LOG_M("Xu_br.m","xu_br",Xu,N_ZC,1,1); LOG_M("prach_ifft0_br.m","prach_t0_br",prach_ifft,1024,1,1); - exit(-1); } } } /* LOG_DUMPFLAG(PRACH) */ if (eNB) stop_meas(&eNB->rx_prach); + AssertFatal(exit_flag==0,"exiting\n"); + } diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 92aea419af..2d86b46742 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -90,9 +90,8 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input if(nb_symbols == 0) return; - short temp[2*2*6144*4] __attribute__((aligned(32))); - unsigned short i,j; - short k; + int16_t temp[2*2*6144*4] __attribute__((aligned(32))); + int i,j; volatile int *output_ptr=(int*)0; @@ -190,18 +189,9 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input if (fftsize==128) #endif { - /*for (j=0; j=-nb_prefix_samples; k--) { - output_ptr[k] = output_ptr[--j]; - } - + memcpy((void*)&output_ptr[-nb_prefix_samples],(void*)&output_ptr[fftsize-nb_prefix_samples],nb_prefix_samples<<2); break; case CYCLIC_SUFFIX: diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index b6388fb903..27c1ef2ac6 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -25,6 +25,7 @@ #include "nr_ul_estimation.h" #include "PHY/sse_intrin.h" #include "PHY/NR_REFSIG/nr_refsig.h" +#include "PHY/NR_REFSIG/dmrs_nr.h" #include "PHY/NR_REFSIG/ptrs_nr.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_UE_ESTIMATION/filt16a_32.h" @@ -533,384 +534,107 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, * 3) Compensated DMRS based estimated signal with PTRS estimation for slot *********************************************************************/ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, + NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul, uint8_t ulsch_id, uint8_t nr_tti_rx, - uint8_t dmrs_symbol_flag, unsigned char symbol, uint32_t nb_re_pusch) { - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - int16_t *phase_per_symbol; - - uint8_t L_ptrs = 0; - uint8_t right_side_ref = 0; - uint8_t left_side_ref = 0; - uint8_t nb_dmrs_in_slot = 0; - //#define DEBUG_UL_PTRS 1 - /* First symbol calculate PTRS symbol index for slot & set the variables */ - if(symbol == rel15_ul->start_symbol_index) - { - gNB->pusch_vars[ulsch_id]->ptrs_symbols = 0; - L_ptrs = 1<<(rel15_ul->pusch_ptrs.ptrs_time_density); - set_ptrs_symb_idx(&gNB->pusch_vars[ulsch_id]->ptrs_symbols, - rel15_ul->nr_of_symbols, - rel15_ul->start_symbol_index, - L_ptrs, - rel15_ul->ul_dmrs_symb_pos); - }/* First symbol check */ + int16_t *phase_per_symbol = NULL; + int32_t *ptrs_re_symbol = NULL; + int8_t ret = 0; + uint8_t symbInSlot = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols; + uint8_t *startSymbIndex = &rel15_ul->start_symbol_index; + uint8_t *nbSymb = &rel15_ul->nr_of_symbols; + uint8_t *L_ptrs = &rel15_ul->pusch_ptrs.ptrs_time_density; + uint8_t *K_ptrs = &rel15_ul->pusch_ptrs.ptrs_freq_density; + uint16_t *dmrsSymbPos = &rel15_ul->ul_dmrs_symb_pos; + uint16_t *ptrsSymbPos = &gNB->pusch_vars[ulsch_id]->ptrs_symbols; + uint8_t *ptrsSymbIdx = &gNB->pusch_vars[ulsch_id]->ptrs_symbol_index; + uint8_t *dmrsConfigType = &rel15_ul->dmrs_config_type; + uint16_t *nb_rb = &rel15_ul->rb_size; + uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset; /* loop over antennas */ - for (int aarx=0; aarx< frame_parms->nb_antennas_rx; aarx++) - { + for (int aarx=0; aarxnb_antennas_rx; aarx++) { phase_per_symbol = (int16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx]; - /* set the previous estimations to zero at first symbol */ - if(symbol == rel15_ul->start_symbol_index) - { - memset(phase_per_symbol,0,sizeof(int32_t)*frame_parms->symbols_per_slot); + ptrs_re_symbol = &gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot; + *ptrs_re_symbol = 0; + phase_per_symbol[(2*symbol)+1] = 0; // Imag + /* set DMRS estimates to 0 angle with magnitude 1 */ + if(is_dmrs_symbol(symbol,*dmrsSymbPos)) { + /* set DMRS real estimation to 32767 */ + phase_per_symbol[2*symbol]=(int16_t)((1<<15)-1); // 32767 +#ifdef DEBUG_UL_PTRS + printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[2*symbol],phase_per_symbol[(2*symbol)+1]); +#endif + } + else {// real ptrs value is set to 0 + phase_per_symbol[2*symbol] = 0; // Real + } + + if(symbol == *startSymbIndex) { + *ptrsSymbPos = 0; + set_ptrs_symb_idx(ptrsSymbPos, + *nbSymb, + *startSymbIndex, + 1<< *L_ptrs, + *dmrsSymbPos); } /* if not PTRS symbol set current ptrs symbol index to zero*/ - gNB->pusch_vars[ulsch_id]->ptrs_symbol_index = 0; - gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol = 0; + *ptrsSymbIdx = 0; /* Check if current symbol contains PTRS */ - if(is_ptrs_symbol(symbol, gNB->pusch_vars[ulsch_id]->ptrs_symbols)) - { - gNB->pusch_vars[ulsch_id]->ptrs_symbol_index = symbol; + if(is_ptrs_symbol(symbol, *ptrsSymbPos)) { + *ptrsSymbIdx = symbol; /*------------------------------------------------------------------------------------------------------- */ - /* 1) Estimate phase noise per PTRS symbol */ + /* 1) Estimate common phase error per PTRS symbol */ /*------------------------------------------------------------------------------------------------------- */ - nr_pusch_phase_estimation(frame_parms, - rel15_ul, - (int16_t *)&gNB->pusch_vars[ulsch_id]->ul_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pusch], - nr_tti_rx, - symbol, - (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(symbol * nb_re_pusch)], - gNB->nr_gold_pusch_dmrs[rel15_ul->scid], - &phase_per_symbol[2* symbol], - &gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol); - } - /* DMRS Symbol channel estimates extraction */ - else if(dmrs_symbol_flag) - { - phase_per_symbol[2* symbol]= (int16_t)((1<<15)-1); // 32767 - phase_per_symbol[2* symbol +1]= 0;// no angle + nr_ptrs_cpe_estimation(*K_ptrs,*ptrsReOffset,*dmrsConfigType,*nb_rb, + rel15_ul->rnti, + (int16_t *)&gNB->pusch_vars[ulsch_id]->ul_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pusch], + nr_tti_rx, + symbol,frame_parms->ofdm_symbol_size, + (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(symbol * nb_re_pusch)], + gNB->nr_gold_pusch_dmrs[rel15_ul->scid][nr_tti_rx][symbol], + &phase_per_symbol[2* symbol], + ptrs_re_symbol); } /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/ - if(symbol == (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols -1)) - { - nb_dmrs_in_slot = get_dmrs_symbols_in_slot(rel15_ul->ul_dmrs_symb_pos,(rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols)); - for(uint8_t dmrs_sym = 0; dmrs_sym < nb_dmrs_in_slot; dmrs_sym ++) - { - if(dmrs_sym == 0) - { - /* get first DMRS position */ - left_side_ref = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols)); - /* get first DMRS position is not at start symbol position then we need to extrapolate left side */ - if(left_side_ref > rel15_ul->start_symbol_index) - { - left_side_ref = rel15_ul->start_symbol_index; - } + if(symbol == (symbInSlot -1)) { + /*------------------------------------------------------------------------------------------------------- */ + /* 2) Interpolate PTRS estimated value in TD */ + /*------------------------------------------------------------------------------------------------------- */ + /* If L-PTRS is > 0 then we need interpolation */ + if(*L_ptrs > 0) { + ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb); + if(ret != 0) { + LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); } - /* get the next symbol from left_side_ref value */ - right_side_ref = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, left_side_ref+1, (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols)); - /* if no symbol found then interpolate till end of slot*/ - if(right_side_ref == 0) - { - right_side_ref = (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); - } - /*------------------------------------------------------------------------------------------------------- */ - /* 2) Interpolate PTRS estimated value in TD */ - /*------------------------------------------------------------------------------------------------------- */ - nr_pusch_phase_interpolation(phase_per_symbol,left_side_ref,right_side_ref); - /* set left to last dmrs */ - left_side_ref = right_side_ref; - } /*loop over dmrs positions */ - + } #ifdef DEBUG_UL_PTRS - LOG_M("ptrsEst.m","est",gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 ); - LOG_M("rxdataF_bf_ptrs_comp.m","bf_ptrs_cmp", + LOG_M("ptrsEstUl.m","est",gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 ); + LOG_M("rxdataF_bf_ptrs_comp_ul.m","bf_ptrs_cmp", &gNB->pusch_vars[0]->rxdataF_comp[aarx][rel15_ul->start_symbol_index * NR_NB_SC_PER_RB * rel15_ul->rb_size], rel15_ul->nr_of_symbols * NR_NB_SC_PER_RB * rel15_ul->rb_size,1,1); #endif - /*------------------------------------------------------------------------------------------------------- */ /* 3) Compensated DMRS based estimated signal with PTRS estimation */ /*--------------------------------------------------------------------------------------------------------*/ - for(uint8_t i =rel15_ul->start_symbol_index; i< (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols);i++) - { + for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++) { + /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */ + /* Skip rotation if the slot processing is wrong */ + if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) { #ifdef DEBUG_UL_PTRS - printf("PTRS: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]); + printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]); #endif - rotate_cpx_vector((int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], - &phase_per_symbol[2* i], - (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], - (rel15_ul->rb_size * NR_NB_SC_PER_RB), - 15); + rotate_cpx_vector((int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + &phase_per_symbol[2* i], + (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + ((*nb_rb) * NR_NB_SC_PER_RB), 15); + }// if not DMRS Symbol }// symbol loop - }//interpolation and compensation - }// Antenna loop -} - -/******************************************************************* - * - * NAME : nr_pusch_phase_estimation - * - * PARAMETERS : frame_parms : UL frame parameters - * rel15_ul : UL PDU Structure - * Ns : - * Symbol : OFDM symbol index - * rxF : Channel compensated signal - * ptrs_gold_seq: Gold sequence for PTRS regeneration - * error_est : Estimated error output vector [Re Im] - * RETURN : nothing - * - * DESCRIPTION : - * perform phase estimation from regenerated PTRS SC and channel compensated - * signal - *********************************************************************/ -void nr_pusch_phase_estimation(NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t *rel15_ul, - int16_t *ptrs_ch_p, - unsigned char Ns, - unsigned char symbol, - int16_t *rxF_comp, - uint32_t ***ptrs_gold_seq, - int16_t *error_est, - uint16_t *ptrs_sc) -{ - uint8_t is_ptrs_re = 0; - uint16_t re_cnt = 0; - uint16_t cnt = 0; - unsigned short nb_re_pusch = NR_NB_SC_PER_RB * rel15_ul->rb_size; - uint8_t K_ptrs = rel15_ul->pusch_ptrs.ptrs_freq_density; - uint16_t sc_per_symbol = (rel15_ul->rb_size + K_ptrs - 1)/K_ptrs; - int16_t *ptrs_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol)); - int16_t *dmrs_comp_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol)); - double abs = 0.0; - double real = 0.0; - double imag = 0.0; -#ifdef DEBUG_UL_PTRS - double alpha = 0; -#endif - /* generate PTRS RE for the symbol */ - nr_gen_ref_conj_symbols(ptrs_gold_seq[Ns][symbol],sc_per_symbol*2,ptrs_p, NR_MOD_TABLE_QPSK_OFFSET,2);// 2 for QPSK - - /* loop over all sub carriers to get compensated RE on ptrs symbols*/ - for (int re = 0; re < nb_re_pusch; re++) - { - is_ptrs_re = is_ptrs_subcarrier(re, - rel15_ul->rnti, - 0, - rel15_ul->dmrs_config_type, - K_ptrs, - rel15_ul->rb_size, - rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset, - 0,// start_re is 0 here - frame_parms->ofdm_symbol_size); - if(is_ptrs_re) - { - dmrs_comp_p[re_cnt*2] = rxF_comp[re *2]; - dmrs_comp_p[(re_cnt*2)+1] = rxF_comp[(re *2)+1]; - re_cnt++; - } - else - { - /* Skip PTRS symbols and keep data in a continuous vector */ - rxF_comp[cnt *2]= rxF_comp[re *2]; - rxF_comp[(cnt *2)+1]= rxF_comp[(re *2)+1]; - cnt++; - } - }/* RE loop */ - /* update the total ptrs RE in a symbol */ - *ptrs_sc = re_cnt; - - /*Multiple compensated data with conj of PTRS */ - mult_cpx_vector(dmrs_comp_p, ptrs_p, ptrs_ch_p,(1 + sc_per_symbol/4)*4,15); // 2^15 shifted - - /* loop over all ptrs sub carriers in a symbol */ - /* sum the error vector */ - for(int i = 0;i < sc_per_symbol; i++) - { - real+= ptrs_ch_p[(2*i)]; - imag+= ptrs_ch_p[(2*i)+1]; - } -#ifdef DEBUG_UL_PTRS - alpha = atan(imag/real); - printf("PTRS: Symbol %d atan(Im,real):= %f \n",symbol, alpha ); -#endif - /* mean */ - real /= sc_per_symbol; - imag /= sc_per_symbol; - /* absolute calculation */ - abs = sqrt(((real * real) + (imag * imag))); - /* normalized error estimation */ - error_est[0]= (real / abs)*(1<<15); - /* compensation in given by conjugate of estimated phase (e^-j*2*pi*fd*t)*/ - error_est[1]= (-1)*(imag / abs)*(1<<15); -#ifdef DEBUG_UL_PTRS - printf("PTRS: Estimated Symbol %d -> %d + j* %d \n",symbol, error_est[0], error_est[1] ); -#endif - /* free vectors */ - free(ptrs_p); - free(dmrs_comp_p); -} - - -/******************************************************************* - * - * NAME : nr_pusch_phase_interpolation - * - * PARAMETERS : *error_est : Data Pointer [Re Im Re Im ...] - * start_symbol : Start Symbol - * end_symbol : End Symbol - * RETURN : nothing - * - * DESCRIPTION : - * Perform Interpolation, extrapolation based upon the estimation - * location between the data Pointer Array. - * - *********************************************************************/ -void nr_pusch_phase_interpolation(int16_t *error_est, - uint8_t start_symbol, - uint8_t end_symbol - ) -{ - - int next = 0, prev = 0, candidates= 0, distance=0, leftEdge= 0, rightEdge = 0, getDiff =0 ; - double weight = 0.0; - double scale = 0.125 ; // to avoid saturation due to fixed point multiplication -#ifdef DEBUG_UL_PTRS - printf("PTRS: INT: Left limit %d, Right limit %d, Loop over %d Symbols \n", - start_symbol,end_symbol-1, (end_symbol -start_symbol)-1); -#endif - for(int i =start_symbol; i< end_symbol;i++) - { - /* Only update when an estimation is found */ - if( error_est[i*2] != 0 ) - { - /* if found a symbol then set next symbol also */ - next = nr_ptrs_find_next_estimate(error_est, i, end_symbol); - /* left extrapolation, if first estimate value is zero */ - if( error_est[i*2] == 0 ) - { - leftEdge = 1; - } - /* right extrapolation, if next is 0 before end symbol */ - if((next == 0) && (end_symbol > i)) - { - rightEdge = 1; - /* special case as no right extrapolation possible with DMRS on left */ - /* In this case take mean of most recent 2 estimated points */ - if(prev ==0) - { - prev = start_symbol -1; - next = start_symbol -2; - getDiff =1; - }else - { - /* for right edge previous is second last from right side */ - next = prev; - /* Set the current as recent estimation reference */ - prev = i; - } - } - /* update current symbol as prev for next symbol */ - if (rightEdge==0) - /* Set the current as recent estimation reference */ - prev = i; - } - /*extrapolation left side*/ - if(leftEdge) - { - distance = next - prev; - weight = 1.0/distance; - candidates = i; - for(int j = 1; j <= candidates; j++) - { - error_est[(i-j)*2] = 8 *(((double)(error_est[prev*2]) * scale * (distance + j) * weight) - - ((double)(error_est[next*2]) * scale * j * weight)); - error_est[((i-j)*2)+1]= 8 *(((double)(error_est[(prev*2)+1]) * scale* (distance + j) * weight) - - ((double)(error_est[((next*2)+1)]) * scale * j * weight)); -#ifdef DEBUG_UL_PTRS - printf("PTRS: INT: Left Edge i= %d weight= %f %d + j*%d, Prev %d Next %d \n", - (i-j),weight, error_est[(i-j)*2],error_est[((i-j)*2)+1], prev,next); -#endif - } - leftEdge = 0; - } - /* extrapolation at right side */ - else if (rightEdge ) - { - if(getDiff) - { - error_est[(i+1)*2] = ((1<<15) +(error_est[prev*2]) - error_est[next*2]); - error_est[((i+1)*2)+1]= error_est[(prev*2)+1] - error_est[(next*2)+1]; -#ifdef DEBUG_UL_PTRS - printf("PTRS: INT: Right Edge Special Case i= %d weight= %f %d + j*%d, Prev %d Next %d \n", - (i+1),weight, error_est[(i+1)*2],error_est[((i+1)*2)+1], prev,next); -#endif - i++; - } - else - { - distance = prev - next; - candidates = (end_symbol -1) - i; - weight = 1.0/distance; - for(int j = 1; j <= candidates; j++) - { - error_est[(i+j)*2] = 8 *(((double)(error_est[prev*2]) * scale * (distance + j) * weight) - - ((double)(error_est[next*2]) * scale * j * weight)); - error_est[((i+j)*2)+1]= 8 *(((double)(error_est[(prev*2)+1]) * scale * (distance + j) * weight) - - ((double)(error_est[((next*2)+1)]) * scale *j * weight)); -#ifdef DEBUG_UL_PTRS - printf("PTRS: INT: Right Edge i= %d weight= %f %d + j*%d, Prev %d Next %d \n", - (i+j),weight, error_est[(i+j)*2],error_est[((i+j)*2)+1], prev,next); -#endif - } - if(candidates > 1) - { - i+=candidates; - } - } - } - /* Interpolation between 2 estimated points */ - else if(next != 0 && ( error_est[2*i] == 0 )) - { - distance = next - prev; - weight = 1.0/distance; - candidates = next - i ; - for(int j = 0; j < candidates; j++) - { - - error_est[(i+j)*2] = 8 *(((double)(error_est[prev*2]) * scale * (distance - (j+1)) * weight) + - ((double)(error_est[next*2]) * scale * (j+1) * weight)); - error_est[((i+j)*2)+1]= 8 *(((double)(error_est[(prev*2)+1]) * scale *(distance - (j+1)) * weight) + - ((double)(error_est[((next*2)+1)]) * scale *(j+1) * weight)); -#ifdef DEBUG_UL_PTRS - printf("PTRS: INT: Interpolation i= %d weight= %f %d + j*%d, Prev %d Next %d\n", - (i+j),weight, error_est[(i+j)*2],error_est[((i+j)*2)+1],prev,next); -#endif - } - if(candidates > 1) - { - i+=candidates-1; - } - }// interpolation - }// symbol loop -} - -/* Find the next non zero Real value in a complex vector */ -int nr_ptrs_find_next_estimate(int16_t *error_est, - uint8_t counter, - uint8_t end_symbol) -{ - for (int i = counter +1 ; i< end_symbol; i++) - { - if( error_est[2*i] != 0) - { - return i; - } - } - return 0; + }// last symbol check + }//Antenna loop } diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 0f71487e36..a463e21839 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -53,28 +53,10 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id); void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, + NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul, uint8_t ulsch_id, uint8_t nr_tti_rx, - uint8_t dmrs_symbol_flag, unsigned char symbol, uint32_t nb_re_pusch); - -void nr_pusch_phase_estimation(NR_DL_FRAME_PARMS *frame_parms, - nfapi_nr_pusch_pdu_t *rel15_ul, - int16_t *ptrs_ch_p, - unsigned char Ns, - unsigned char symbol, - int16_t *rxF_comp, - uint32_t ***ptrs_gold_seq, - int16_t *error_est, - uint16_t *ptrs_sc); - -void nr_pusch_phase_interpolation(int16_t *error_est, - uint8_t start_symbol, - uint8_t end_symbol); - -int nr_ptrs_find_next_estimate(int16_t *error_est, - uint8_t counter, - uint8_t end_symbol); #endif diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.c b/openair1/PHY/NR_REFSIG/dmrs_nr.c index 72cb60003e..03a37e2b27 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.c +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.c @@ -364,14 +364,14 @@ void generate_dmrs_pbch(uint32_t dmrs_pbch_bitmap[DMRS_PBCH_I_SSB][DMRS_PBCH_N_H #endif } /* return the position of next dmrs symbol in a slot */ -int get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol) +int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol) { - for(uint8_t symbol = counter; symbol < end_symbol; symbol++) - if((ul_dmrs_symb_pos >>symbol)&0x01 ) - { + for(uint8_t symbol = counter; symbol < end_symbol; symbol++) { + if((ul_dmrs_symb_pos >> symbol) & 0x01 ) { return symbol; } - return 0; + } + return -1; } @@ -379,9 +379,30 @@ int get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, ui uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb) { uint8_t tmp = 0; - for (int i = 0; i < nb_symb; i++) - { + for (int i = 0; i < nb_symb; i++) { tmp += (l_prime_mask >> i) & 0x01; } return tmp; } + +/* return the position of valid dmrs symbol in a slot for channel compensation */ +int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter) +{ + int8_t symbIdx = -1; + /* if current symbol is DMRS then return this index */ + if(is_dmrs_symbol(counter, dmrs_symb_pos ) ==1) { + return counter; + } + /* find previous DMRS symbol */ + for(int8_t symbol = counter;symbol >=0 ; symbol--) { + if((1< 0) { + symbIdx = symbol; + break; + } + } + /* if there is no previous dmrs available then find the next possible*/ + if(symbIdx == -1) { + symbIdx = get_next_dmrs_symbol_in_slot(dmrs_symb_pos,counter,15); + } + return symbIdx; +} diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.h b/openair1/PHY/NR_REFSIG/dmrs_nr.h index 860f997734..b9e9ca6f0d 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.h +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.h @@ -62,6 +62,12 @@ uint8_t allowed_xlsch_re_in_dmrs_symbol(uint16_t k, uint8_t numDmrsCdmGrpsNoData, uint8_t dmrs_type); +void nr_gen_ref_conj_symbols(uint32_t *in, uint32_t length, int16_t *output, uint16_t offset, int mod_order); +int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol); +uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb); +int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter); + +static inline uint8_t is_dmrs_symbol(uint8_t l, uint16_t dmrsSymbMask ) { return ((dmrsSymbMask >> l) & 0x1); } #undef EXTERN #endif /* DMRS_NR_H */ diff --git a/openair1/PHY/NR_REFSIG/nr_gold_ue.c b/openair1/PHY/NR_REFSIG/nr_gold_ue.c index 39ab13b1f1..414582a31d 100644 --- a/openair1/PHY/NR_REFSIG/nr_gold_ue.c +++ b/openair1/PHY/NR_REFSIG/nr_gold_ue.c @@ -107,9 +107,7 @@ void nr_gold_pdcch(PHY_VARS_NR_UE* ue, } void nr_gold_pdsch(PHY_VARS_NR_UE* ue, - unsigned short lbar, - unsigned short *n_idDMRS, - unsigned short length_dmrs) + unsigned short *n_idDMRS) { unsigned char ns,l; unsigned int n,x1,x2,x2tmp0; @@ -129,12 +127,12 @@ void nr_gold_pdsch(PHY_VARS_NR_UE* ue, for (ns=0; ns<20; ns++) { - for (l=0; l>1) ^ (x2>>2) ^ (x2>>3))<<31); @@ -145,7 +143,7 @@ void nr_gold_pdsch(PHY_VARS_NR_UE* ue, x1 = x1 ^ (x1<<31) ^ (x1<<28); x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); - //printf("x1 : %x, x2 : %x\n",x1,x2); + //printf("x1 : %x, x2 : %x\n",x1,x2); } for (n=0; n>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4); x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28); ue->nr_gold_pdsch[nscid][ns][l][n] = x1^x2; - // if ((ns==2)&&(l==0)) - //printf("n=%d : c %x\n",n,x1^x2); + // if ((ns==2)&&(l==0)) + //printf("n=%d : c %x\n",n,x1^x2); } } diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index f82a7880bb..c5bba196a5 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -53,10 +53,6 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB, uint8_t dmrs_type); void init_scrambling_luts(void); -void nr_gen_ref_conj_symbols(uint32_t *in, uint32_t length, int16_t *output, uint16_t offset, int mod_order); -uint8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol); -uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb); - void nr_generate_modulation_table(void); extern __m64 byte2m64_re[256]; diff --git a/openair1/PHY/NR_REFSIG/ptrs_nr.c b/openair1/PHY/NR_REFSIG/ptrs_nr.c index 785252126a..b50c9a7bc9 100644 --- a/openair1/PHY/NR_REFSIG/ptrs_nr.c +++ b/openair1/PHY/NR_REFSIG/ptrs_nr.c @@ -34,7 +34,7 @@ #include #include "dmrs_nr.h" #include "PHY/NR_REFSIG/ptrs_nr.h" - +#include "PHY/NR_REFSIG/nr_refsig.h" /***********************************************************************/ @@ -180,93 +180,249 @@ uint8_t is_ptrs_subcarrier(uint16_t k, return 0; } - -/* -int main(int argc, char const *argv[]) +/* return the total number of ptrs symbol in a slot */ +uint8_t get_ptrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t start_symb, uint16_t nb_symb) { - - dmrs_UplinkConfig_t dmrs_Uplink_Config; - ptrs_UplinkConfig_t ptrs_Uplink_Config; - uint8_t resourceElementOffset; - uint8_t dmrs_antenna_port; - uint8_t L_ptrs, K_ptrs; - int16_t k_RE_ref; - uint16_t N_RB, ptrs_symbols, ofdm_symbol_size, k; - uint8_t duration_in_symbols, I_mcs; - uint8_t start_symbol, l; - uint8_t ptrs_symbol_flag; - uint16_t n_rnti; - - dmrs_Uplink_Config.pusch_dmrs_type = pusch_dmrs_type1; - dmrs_Uplink_Config.pusch_dmrs_AdditionalPosition = pusch_dmrs_pos1; - dmrs_Uplink_Config.pusch_maxLength = pusch_len2; - - ptrs_Uplink_Config.timeDensity.ptrs_mcs1 = 0; // setting MCS values to 0 indicate abscence of time_density field in the configuration - ptrs_Uplink_Config.timeDensity.ptrs_mcs2 = 0; - ptrs_Uplink_Config.timeDensity.ptrs_mcs3 = 0; - ptrs_Uplink_Config.frequencyDensity.n_rb0 = 0; // setting N_RB values to 0 indicate abscence of frequency_density field in the configuration - ptrs_Uplink_Config.frequencyDensity.n_rb1 = 0; - ptrs_Uplink_Config.resourceElementOffset = 0; - - n_rnti = 0x1234; - resourceElementOffset = 0; - ptrs_symbols = 0; - dmrs_antenna_port = 0; - N_RB = 50; - duration_in_symbols = 14; - ofdm_symbol_size = 2048; - I_mcs = 9; - start_symbol = 0; - ptrs_symbol_flag = 0; - - k_RE_ref = get_kRE_ref(dmrs_antenna_port, dmrs_Uplink_Config.pusch_dmrs_type, resourceElementOffset); - - K_ptrs = get_K_ptrs(&ptrs_Uplink_Config, N_RB); - - L_ptrs = get_L_ptrs(&ptrs_Uplink_Config, I_mcs); - - set_ptrs_symb_idx(&ptrs_symbols, - &ptrs_Uplink_Config, - &dmrs_Uplink_Config, - 1, - duration_in_symbols, - start_symbol, - L_ptrs, - ofdm_symbol_size); - - printf("PTRS OFDM symbol indicies: "); - - for (l = start_symbol; l < start_symbol + duration_in_symbols; l++){ - - ptrs_symbol_flag = is_ptrs_symbol(l, - 0, - n_rnti, - N_RB, - duration_in_symbols, - dmrs_antenna_port, - K_ptrs, - ptrs_symbols, - dmrs_Uplink_Config.pusch_dmrs_type, - &ptrs_Uplink_Config); - - if (ptrs_symbol_flag == 1) - printf(" %d ", l); - + uint8_t tmp = 0; + for (int i = start_symb; i <= nb_symb; i++) + { + tmp += (l_prime_mask >> i) & 0x01; } + return tmp; +} - printf("\n"); - - printf("PTRS subcarrier indicies: "); - - for (k = 0; k < N_RB*12; k++){ - - if (is_ptrs_subcarrier(k, K_ptrs, n_rnti, N_RB, k_RE_ref) == 1) - printf(" %d ", k); - +/* return the position of next ptrs symbol in a slot */ +int8_t get_next_ptrs_symbol_in_slot(uint16_t ptrs_symb_pos, uint8_t counter, uint8_t nb_symb) +{ + for(int8_t symbol = counter; symbol < nb_symb; symbol++) { + if((ptrs_symb_pos >>symbol)&0x01 ) { + return symbol; } + } + return -1; +} - printf("\n"); +/* get the next nearest estimate from DMRS or PTRS */ +int8_t get_next_estimate_in_slot(uint16_t ptrsSymbPos,uint16_t dmrsSymbPos, uint8_t counter,uint8_t nb_symb) +{ + int8_t nextPtrs = get_next_ptrs_symbol_in_slot(ptrsSymbPos, counter,nb_symb); + int8_t nextDmrs = get_next_dmrs_symbol_in_slot(dmrsSymbPos, counter,nb_symb); + if(nextDmrs == -1) { + return nextPtrs; + } + /* Special case when DMRS is next valid estimation */ + if(nextPtrs == -1) { + return nextDmrs; + } + return (nextPtrs > nextDmrs)?nextDmrs:nextPtrs; +} +/******************************************************************* + * + * NAME : nr_ptrs_cpe_estimation + * + * PARAMETERS : K_ptrs : K value for PTRS + * ptrsReOffset : RE offset for PTRS + * dmrsConfigType: DMRS configuration type + * nb_rb : No. of resource blocks + * rnti : RNTI + * ptrs_ch_p : pointer to ptrs channel structure + * Ns : + * symbol : OFDM symbol + * ofdm_symbol_size: OFDM Symbol Size + * rxF_comp : pointer to channel compensated signal + * gold_seq : Gold sequence pointer + * error_est : Estimated error output vector [Re Im] + * ptrs_sc : Total PTRS RE in a symbol + * RETURN : nothing + * + * DESCRIPTION : + * perform phase estimation from regenerated PTRS SC and channel compensated + * signal + *********************************************************************/ +void nr_ptrs_cpe_estimation(uint8_t K_ptrs, + uint8_t ptrsReOffset, + uint8_t dmrsConfigType, + uint16_t nb_rb, + uint16_t rnti, + int16_t *ptrs_ch_p, + unsigned char Ns, + unsigned char symbol, + uint16_t ofdm_symbol_size, + int16_t *rxF_comp, + uint32_t *gold_seq, + int16_t *error_est, + int32_t *ptrs_sc) +{ +//#define DEBUG_PTRS 1 + uint8_t is_ptrs_re = 0; + uint16_t re_cnt = 0; + uint16_t cnt = 0; + unsigned short nb_re_pdsch = NR_NB_SC_PER_RB * nb_rb; + uint16_t sc_per_symbol = (nb_rb + K_ptrs - 1)/K_ptrs; + int16_t *ptrs_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol)); + int16_t *dmrs_comp_p = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol)); + double abs = 0.0; + double real = 0.0; + double imag = 0.0; +#ifdef DEBUG_PTRS + double alpha = 0; +#endif + /* generate PTRS RE for the symbol */ + nr_gen_ref_conj_symbols(gold_seq,sc_per_symbol*2,ptrs_p, NR_MOD_TABLE_QPSK_OFFSET,2);// 2 for QPSK + + /* loop over all sub carriers to get compensated RE on ptrs symbols*/ + for (int re = 0; re < nb_re_pdsch; re++) { + is_ptrs_re = is_ptrs_subcarrier(re, + rnti, + 0, + dmrsConfigType, + K_ptrs, + nb_rb, + ptrsReOffset, + 0,// start_re is 0 here + ofdm_symbol_size); + if(is_ptrs_re) { + dmrs_comp_p[re_cnt*2] = rxF_comp[re *2]; + dmrs_comp_p[(re_cnt*2)+1] = rxF_comp[(re *2)+1]; + re_cnt++; + } + else { + /* Skip PTRS symbols and keep data in a continuous vector */ + rxF_comp[cnt *2]= rxF_comp[re *2]; + rxF_comp[(cnt *2)+1]= rxF_comp[(re *2)+1]; + cnt++; + } + }/* RE loop */ + /* update the total ptrs RE in a symbol */ + *ptrs_sc = re_cnt; + + /*Multiple compensated data with conj of PTRS */ + mult_cpx_vector(dmrs_comp_p, ptrs_p, ptrs_ch_p,(1 + sc_per_symbol/4)*4,15); // 2^15 shifted + + /* loop over all ptrs sub carriers in a symbol */ + /* sum the error vector */ + for(int i = 0;i < sc_per_symbol; i++) { + real+= ptrs_ch_p[(2*i)]; + imag+= ptrs_ch_p[(2*i)+1]; + } +#ifdef DEBUG_PTRS + alpha = atan(imag/real); + printf("[PHY][PTRS]: Symbol %d atan(Im,real):= %f \n",symbol, alpha ); +#endif + /* mean */ + real /= sc_per_symbol; + imag /= sc_per_symbol; + /* absolute calculation */ + abs = sqrt(((real * real) + (imag * imag))); + /* normalized error estimation */ + error_est[0]= (real / abs)*(1<<15); + /* compensation in given by conjugate of estimated phase (e^-j*2*pi*fd*t)*/ + error_est[1]= (-1)*(imag / abs)*(1<<15); +#ifdef DEBUG_PTRS + printf("[PHY][PTRS]: Estimated Symbol %d -> %d + j* %d \n",symbol, error_est[0], error_est[1] ); +#endif + /* free vectors */ + free(ptrs_p); + free(dmrs_comp_p); +} + + +/******************************************************************* + * + * NAME : nr_ptrs_process_slot + * + * PARAMETERS : dmrsSymbPos DMRS symbol index mask per slot + * ptrsSymbpos PTRS symbol index mask per slot + * estPerSymb Estimated CPE pointer + * startSymbIdx First symbol index in a slot + * noSymb total number of OFDM symbols in a slot + * RETURN : True if slot is process correctly + * DESCRIPTION : + * Process whole slot and interpolate or extrapolate estimation for the symbols + * where there is neither PTRS nor DMRS configured + * + *********************************************************************/ +int8_t nr_ptrs_process_slot(uint16_t dmrsSymbPos, + uint16_t ptrsSymbPos, + int16_t *estPerSymb, + uint16_t startSymbIdx, + uint16_t noSymb) +{ + double slope[2] = {0,0}; + double *slope_p = &slope[0]; + uint8_t symbInSlot = startSymbIdx + noSymb; + int8_t rightRef = 0; + int8_t leftRef = 0; + int8_t tmp = 0; + for(uint8_t symb = startSymbIdx; symb %4d %4d from Slope (%4f %4f)\n", start+i,error_est[(start+i)*2],error_est[((start +i)*2)+1], + slope_p[0],slope_p[1]); +#endif + } +} diff --git a/openair1/PHY/NR_REFSIG/ptrs_nr.h b/openair1/PHY/NR_REFSIG/ptrs_nr.h index e8a4e61232..41acde0d06 100644 --- a/openair1/PHY/NR_REFSIG/ptrs_nr.h +++ b/openair1/PHY/NR_REFSIG/ptrs_nr.h @@ -80,6 +80,31 @@ uint8_t is_ptrs_subcarrier(uint16_t k, static inline uint8_t is_ptrs_symbol(uint8_t l, uint16_t ptrs_symbols) { return ((ptrs_symbols >> l) & 1); } +uint8_t get_ptrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t start_symb, uint16_t nb_symb); +int8_t get_next_ptrs_symbol_in_slot(uint16_t ptrsSymbPos, uint8_t counter, uint8_t nb_symb); +int8_t get_next_estimate_in_slot(uint16_t ptrsSymbPos,uint16_t dmrsSymbPos, uint8_t counter,uint8_t nb_symb); +int8_t nr_ptrs_process_slot(uint16_t dmrsSymbPos, + uint16_t ptrsSymbPos, + int16_t *estPerSymb, + uint16_t startSymbIdx, + uint16_t noSymb + ); +/* general function to estimate common phase error based upon PTRS */ +void nr_ptrs_cpe_estimation(uint8_t K_ptrs, + uint8_t ptrsReOffset, + uint8_t dmrsConfigType, + uint16_t nb_rb, + uint16_t rnti, + int16_t *ptrs_ch_p, + unsigned char Ns, + unsigned char symbol, + uint16_t ofdm_symbol_size, + int16_t *rxF_comp, + uint32_t *gold_seq, + int16_t *error_est, + int32_t *ptrs_sc); +void get_slope_from_estimates(uint8_t start, uint8_t end, int16_t *est_p, double *slope_p); +void ptrs_estimate_from_slope(int16_t *error_est, double *slope_p, uint8_t start, uint8_t end); #endif /* PTRS_NR_H */ diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index 93a64051de..f349cfcd98 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -61,9 +61,7 @@ void nr_gold_pdcch(PHY_VARS_NR_UE* ue, unsigned short length_dmrs); void nr_gold_pdsch(PHY_VARS_NR_UE* ue, - unsigned short lbar, - unsigned short *n_idDMRS, - unsigned short length_dmrs); + unsigned short *n_idDMRS); void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue, uint16_t *N_n_scid, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 7b275ea981..d1b868eac8 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -35,7 +35,9 @@ #include "nr_sch_dmrs.h" #include "PHY/MODULATION/nr_modulation.h" #include "PHY/NR_REFSIG/dmrs_nr.h" +#include "PHY/NR_REFSIG/ptrs_nr.h" #include "common/utils/LOG/vcd_signal_dumper.h" +#include "LAYER2/NR_MAC_gNB/mac_proto.h" //#define DEBUG_DLSCH //#define DEBUG_DLSCH_MAPPING @@ -117,8 +119,8 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, uint32_t ***pdsch_dmrs = gNB->nr_gold_pdsch_dmrs[slot]; int32_t** txdataF = gNB->common_vars.txdataF; int16_t amp = AMP; - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; int xOverhead = 0; + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; time_stats_t *dlsch_encoding_stats=&gNB->dlsch_encoding_stats; time_stats_t *dlsch_scrambling_stats=&gNB->dlsch_scrambling_stats; time_stats_t *dlsch_modulation_stats=&gNB->dlsch_modulation_stats; @@ -152,13 +154,31 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1; } - uint16_t nb_re; - nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs-xOverhead)*rel15->rbSize*rel15->nrOfLayers; + + uint16_t dmrs_symbol_map = rel15->dlDmrsSymbPos;//single DMRS: 010000100 Double DMRS 110001100 + uint8_t dmrs_len = get_num_dmrs(rel15->dlDmrsSymbPos); + uint16_t nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs*dmrs_len-xOverhead)*rel15->rbSize*rel15->nrOfLayers; uint8_t Qm = rel15->qamModOrder[0]; uint32_t encoded_length = nb_re*Qm; int16_t mod_dmrs[14][n_dmrs] __attribute__ ((aligned(16))); - - + + /* PTRS */ + uint16_t beta_ptrs = 1; + uint8_t ptrs_symbol = 0; + uint16_t dlPtrsSymPos = 0; + uint16_t n_ptrs = 0; + uint16_t ptrs_idx = 0; + uint8_t is_ptrs_re = 0; + if(rel15->pduBitmap & 0x1) { + set_ptrs_symb_idx(&dlPtrsSymPos, + rel15->NrOfSymbols, + rel15->StartSymbolIndex, + 1<PTRSTimeDensity, + rel15->dlDmrsSymbPos); + n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1)/rel15->PTRSFreqDensity; + } + int16_t mod_ptrs[n_ptrs<<1] __attribute__ ((aligned(16))); + /// CRC, coding, interleaving and rate matching AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); start_meas(dlsch_encoding_stats); @@ -251,22 +271,21 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, /// DMRS QPSK modulation for (int l=rel15->StartSymbolIndex; lStartSymbolIndex+rel15->NrOfSymbols; l++) { - if (rel15->dlDmrsSymbPos & (1 << l)) + if (rel15->dlDmrsSymbPos & (1 << l)) { nr_modulation(pdsch_dmrs[l][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated - } #ifdef DEBUG_DLSCH - l0 = get_l0(rel15->dlDmrsSymbPos); - printf("DMRS modulation (single symbol %d, %d symbols, type %d):\n", l0, n_dmrs>>1, dmrs_Type); - for (int i=0; i>4; i++) { - for (int j=0; j<8; j++) { - printf("%d %d\t", mod_dmrs[((i<<3)+j)<<1], mod_dmrs[(((i<<3)+j)<<1)+1]); - } - printf("\n"); - } + printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs>>1, dmrs_Type); + for (int i=0; i>4; i++) { + for (int j=0; j<8; j++) { + printf("%d %d\t", mod_dmrs[l][((i<<3)+j)<<1], mod_dmrs[l][(((i<<3)+j)<<1)+1]); + } + printf("\n"); + } #endif - - + } + } + /// Resource mapping // Non interleaved VRB to PRB mapping @@ -293,30 +312,63 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, printf("DMRS Type %d params for ap %d: Wt %d %d \t Wf %d %d \t delta %d \t l_prime %d \t l0 %d\tDMRS symbol %d\n", 1+dmrs_Type,ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime, l0, dmrs_symbol); #endif - uint8_t k_prime=0; - uint16_t m=0, n=0, dmrs_idx=0, k=0; - + + uint16_t m=0, dmrs_idx=0, k=0; + int txdataF_offset = (slot%2)*frame_parms->samples_per_slot_wCP; + // Loop Over OFDM symbols: for (int l=rel15->StartSymbolIndex; lStartSymbolIndex+rel15->NrOfSymbols; l++) { + /// DMRS QPSK modulation + uint8_t k_prime=0; + uint16_t n=0; + if ((dmrs_symbol_map & (1 << l))){ //DMRS time occasion + if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) // another if condition to be included to check pdsch config type (reference of k) + dmrs_idx = rel15->rbStart*6; + else + dmrs_idx = rel15->rbStart*4; + } + + // Update l_prime in the case of double DMRS config + if ((dmrs_symbol_map & (1 << l))){ //DMRS time occasion + if (l==(l_overline+1)) //take into account the double DMRS symbols + l_prime = 1; + else if (l>(l_overline+1)) {//new DMRS pair + l_overline = l; + l_prime = 0; + } + } + + /* calculate if current symbol is PTRS symbols */ + ptrs_idx = 0; + + if(rel15->pduBitmap & 0x1) { + ptrs_symbol = is_ptrs_symbol(l,dlPtrsSymPos); + if(ptrs_symbol) { + /* PTRS QPSK Modulation for each OFDM symbol in a slot */ + nr_modulation(pdsch_dmrs[l][0], (n_ptrs<<1), DMRS_MOD_ORDER, mod_ptrs); + } + } k = start_sc; - n = 0; - k_prime = 0; - if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) // another if condition to be included to check pdsch config type (reference of k) - dmrs_idx = rel15->rbStart*6; - else - dmrs_idx = rel15->rbStart*4; + // Loop Over SCs: for (int i=0; irbSize*NR_NB_SC_PER_RB; i++) { + /* check if cuurent RE is PTRS RE*/ + is_ptrs_re=0; + /* check for PTRS symbol and set flag for PTRS RE */ + if(ptrs_symbol){ + is_ptrs_re = is_ptrs_subcarrier(k, + rel15->rnti, + ap, + rel15->dmrsConfigType, + rel15->PTRSFreqDensity, + rel15->rbSize, + rel15->PTRSReOffset, + start_sc, + frame_parms->ofdm_symbol_size); + } - if ((rel15->dlDmrsSymbPos & (1 << l)) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) { - - if (l==(l_overline+1)) //take into account the double DMRS symbols - l_prime = 1; - else if (l>(l_overline+1)) {//new DMRS pair - l_overline = l; - l_prime = 0; - } - + /* Map DMRS Symbol */ + if ( ( dmrs_symbol_map & (1 << l) ) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) { ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[l][dmrs_idx<<1]) >> 15; ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15; #ifdef DEBUG_DLSCH_MAPPING @@ -328,10 +380,21 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB, k_prime++; k_prime&=1; n+=(k_prime)?0:1; - - } else { - - if( (!(rel15->dlDmrsSymbPos & (1 << l))) || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,frame_parms->ofdm_symbol_size,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) { + } + /* Map PTRS Symbol */ + else if(is_ptrs_re){ + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[ptrs_idx<<1]) >> 15; + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[(ptrs_idx<<1) + 1])>> 15; +#ifdef DEBUG_DLSCH_MAPPING + printf("ptrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n", + ptrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)], + ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]); +#endif + ptrs_idx++; + } + /* Map DATA Symbol */ + else { + if( (!(dmrs_symbol_map & (1 << l))) || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,frame_parms->ofdm_symbol_size,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) { ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15; ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15; #ifdef DEBUG_DLSCH_MAPPING diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 80d6d13d9e..cb395ff4af 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -328,8 +328,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, uint16_t nb_rb = rel15->rbSize; uint8_t nb_symb_sch = rel15->NrOfSymbols; uint32_t A, Kb, F=0; - static uint32_t Z = 0; - uint32_t *Zc = &Z; + uint32_t *Zc = &dlsch->harq_processes[harq_pid]->Z; uint8_t mod_order = rel15->qamModOrder[0]; uint16_t Kr=0,r; uint32_t r_offset=0; diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index ba0705cde7..b5a3c061e9 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -185,10 +185,10 @@ void rx_nr_prach_ru(RU_t *ru, for (int aa=0; aanb_rx; aa++){ if (prach_sequence_length == 0) slot2=(slot/fp->slots_per_subframe)*fp->slots_per_subframe; - prach[aa] = (int16_t*)&ru->common.rxdata[aa][(slot2*fp->get_samples_per_slot(slot,fp))+sample_offset_slot-ru->N_TA_offset]; + prach[aa] = (int16_t*)&ru->common.rxdata[aa][fp->get_samples_slot_timestamp(slot2,fp,0)+sample_offset_slot-ru->N_TA_offset]; } - + idft_size_idx_t dftsize; int dftlen=0; int mu = fp->numerology_index; int Ncp = 0; @@ -269,7 +269,8 @@ void rx_nr_prach_ru(RU_t *ru, if (LOG_DEBUGFLAG(PRACH)) { LOG_D(PHY,"rx_prach: Doing PRACH FFT for nb_rx:%d Ncp:%d\n",ru->nb_rx, Ncp); } - AssertFatal(mu==1,"only 30 kHz SCS handled for now\n"); + + // Note: Assumes PUSCH SCS @ 30 kHz, take values for formats 0-2 and adjust for others below int kbar = 1; @@ -299,6 +300,7 @@ void rx_nr_prach_ru(RU_t *ru, AssertFatal(prach[aa]!=NULL,"prach[%d] is null\n",aa); // do DFT + if (mu==1) { if (fp->N_RB_UL <= 100) AssertFatal(1==0,"N_RB_UL %d not support for NR PRACH yet\n",fp->N_RB_UL); else if (fp->N_RB_UL < 137) { @@ -327,36 +329,29 @@ void rx_nr_prach_ru(RU_t *ru, } }// 839 sequence else { - if ((mu==0 && - (prachStartSymbol == 0 || prachStartSymbol == 7)) || - (mu==1 && prachStartSymbol == 0)) prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) + if (prachStartSymbol == 0) + prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) - if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==1) { - dftlen=2048; - dft(DFT_2048,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1); - reps++; - } - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1); - dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1); - dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1); - reps+=6; - } + dftlen=2048; + dft(DFT_2048,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1); + reps++; + } + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1); + dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1); + dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1); + reps+=6; } - else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); } } else { // threequarter sampling // 40 MHz @ 46.08 Ms/s @@ -383,36 +378,28 @@ void rx_nr_prach_ru(RU_t *ru, reps=4; } } else { - if ((mu==0 && - (prachStartSymbol == 0 || prachStartSymbol == 7)) || - (mu==1 && prachStartSymbol == 0)) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only) - if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==1) { - dftlen=1536; - dft(DFT_1536,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1); - dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1); - dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1); - reps+=6; - } - }// mu==1 - else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); + if (prachStartSymbol == 0) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only) + dftlen=1536; + dft(DFT_1536,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1); + dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1); + dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1); + reps+=6; + } } // short format } // 3/4 sampling } // <=50 MHz BW @@ -442,37 +429,29 @@ void rx_nr_prach_ru(RU_t *ru, } } else { - if ((mu==0 && - (prachStartSymbol == 0 || prachStartSymbol == 7)) || - (mu==1 && prachStartSymbol == 0)) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + if (prachStartSymbol == 0) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) - if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==1) { - dftlen=4096; - dft(DFT_4096,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1); - dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1); - dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1); - reps+=6; - } + dftlen=4096; + dft(DFT_4096,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1); + dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1); + dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1); + reps+=6; } - else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); } } else { AssertFatal(fp->N_RB_UL <= 217,"cannot do more than 217 PRBs with 3/4 sampling\n"); @@ -494,40 +473,85 @@ void rx_nr_prach_ru(RU_t *ru, reps=4; } } else { - if ((mu==0 && - (prachStartSymbol == 0 || prachStartSymbol == 7)) || - (mu==1 && prachStartSymbol == 0)) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) + if (prachStartSymbol == 0) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) - if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==1) { - dftlen=3072; - dft(DFT_3072,prach2,rxsigF[aa],1); - if (prachFormat != 9/*C0*/) { - dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); - reps++; - } - - if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { - dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1); - dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1); - reps+=2; - } - if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { - dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1); - dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1); - reps+=2; - } - if (prachFormat == 8/*B4*/) { - for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1); - reps+=6; - } + dftlen=3072; + dft(DFT_3072,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1); + dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1); + dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1); + reps+=6; } - else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n"); - else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n"); } } } + } + else if (mu==3) { + if (fp->threequarter_fs) { + AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu); + } + if (prach_sequence_length == 0) { + AssertFatal(1==0,"long prach not supported for numerology %d\n",mu); + } + if (fp->N_RB_UL == 32) { + prach2 = prach[aa] + (Ncp<<2); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 for 61.44Msps + if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) + prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe + dftlen=512; + dftsize = DFT_512; + } + else if (fp->N_RB_UL == 66) { + prach2 = prach[aa] + (Ncp<<3); // Ncp is for 30.72 Ms/s, so multiply by 4 for I/Q, and 2 for 122.88Msps + if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) + prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe + dftlen=1024; + dftsize = DFT_1024; + } + else { + AssertFatal(1==0,"N_RB_UL %d not support for numerology %d\n",fp->N_RB_UL,mu); + } + + dft(dftsize,prach2,rxsigF[aa],1); + if (prachFormat != 9/*C0*/) { + dft(dftsize,prach2+dftlen*2,rxsigF[aa]+dftlen*2,1); + reps++; + } + + if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) { + dft(dftsize,prach2+dftlen*4,rxsigF[aa]+dftlen*4,1); + dft(dftsize,prach2+dftlen*6,rxsigF[aa]+dftlen*6,1); + reps+=2; + } + if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) { + dft(dftsize,prach2+dftlen*8,rxsigF[aa]+dftlen*8,1); + dft(dftsize,prach2+dftlen*10,rxsigF[aa]+dftlen*10,1); + reps+=2; + } + if (prachFormat == 8/*B4*/) { + for (int i=6;i<12;i++) + dft(dftsize,prach2+(dftlen*2*i),rxsigF[aa]+(dftlen*2*i),1); + reps+=6; + } + } + else { + AssertFatal(1==0,"Numerology not supported\n"); + } + + //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); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 4622c31db3..1372250aca 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1234,16 +1234,16 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, { start_meas(&gNB->ulsch_ptrs_processing_stats); nr_pusch_ptrs_processing(gNB, + frame_parms, rel15_ul, ulsch_id, nr_tti_rx, - dmrs_symbol_flag, symbol, nb_re_pusch); stop_meas(&gNB->ulsch_ptrs_processing_stats); /* Subtract total PTRS RE's in the symbol from PUSCH RE's */ - gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] -= gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol; + gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] -= gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot; } /*---------------------------------------------------------------------------------------------------- */ diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index 143871e2be..4b36180b58 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -33,12 +33,12 @@ // last channel estimate of the receiver void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, - PHY_VARS_NR_UE *ue, - module_id_t gNB_id, - uint8_t frame, - uint8_t subframe, - unsigned char clear, - short coef) + PHY_VARS_NR_UE *ue, + module_id_t gNB_id, + uint8_t frame, + uint8_t subframe, + unsigned char clear, + short coef) { static int max_pos_fil = 0; @@ -47,6 +47,7 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, int temp = 0, i, aa, max_val = 0, max_pos = 0; int diff; short Re,Im,ncoef; + uint8_t sync_offset = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); @@ -80,11 +81,14 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, // do not filter to have proactive timing adjustment //max_pos_fil = max_pos; - if(subframe == 0) - { diff = max_pos_fil - (frame_parms->nb_prefix_samples>>3); - if ( abs(diff) < SYNCH_HYST ) + if (frame_parms->freq_range==nr_FR2) + sync_offset = 2; + else + sync_offset = 0; + + if ( abs(diff) < (SYNCH_HYST+sync_offset) ) ue->rx_offset = 0; else ue->rx_offset = diff; @@ -134,5 +138,5 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, #endif //DEBUG_PHY VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); - } + } 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 bbf4036ab8..0a37f7d6ad 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -24,6 +24,9 @@ #include "SCHED_NR_UE/defs.h" #include "nr_estimation.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_REFSIG/nr_refsig.h" +#include "PHY/NR_REFSIG/dmrs_nr.h" +#include "PHY/NR_REFSIG/ptrs_nr.h" #include "PHY/NR_TRANSPORT/nr_sch_dmrs.h" #include "filt16a_32.h" @@ -667,7 +670,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, int **dl_ch_estimates =ue->pdsch_vars[proc->thread_id][eNB_offset]->dl_ch_estimates; int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF; - if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage + if (ue->high_speed_flag == 0) ch_offset = ue->frame_parms.ofdm_symbol_size ; else ch_offset = ue->frame_parms.ofdm_symbol_size*symbol; @@ -686,7 +689,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, uint16_t rb_offset = (bwp_start_subcarrier - ue->frame_parms.first_carrier_offset) / 12; uint8_t config_type = ue->dmrs_DownlinkConfig.pdsch_dmrs_type; int8_t delta = get_delta(p, config_type); - nr_pdsch_dmrs_rx(ue,Ns,ue->nr_gold_pdsch[eNB_offset][Ns][0], &pilot[0],1000+p,0,nb_rb_pdsch+rb_offset); + nr_pdsch_dmrs_rx(ue,Ns,ue->nr_gold_pdsch[eNB_offset][Ns][symbol], &pilot[0],1000,0,nb_rb_pdsch+rb_offset); if (config_type == pdsch_dmrs_type1){ nushift = (p>>1)&1; @@ -1196,3 +1199,168 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, } return(0); } + +/******************************************************************* + * + * NAME : nr_pdsch_ptrs_processing + * + * PARAMETERS : ue : ue data structure + * NR_UE_PDSCH : pdsch_vars pointer + * NR_DL_FRAME_PARMS : frame_parms pointer + * NR_DL_UE_HARQ_t : dlsch0_harq pointer + * NR_DL_UE_HARQ_t : dlsch1_harq pointer + * uint8_t : eNB_id, + * uint8_t : nr_slot_rx, + * unsigned char : symbol, + * uint32_t : nb_re_pdsch, + * unsigned char : harq_pid + * uint16_t : rnti + * RX_type_t : rx_type + * RETURN : Nothing + * + * DESCRIPTION : + * If ptrs is enabled process the symbol accordingly + * 1) Estimate common phase error per PTRS symbol + * 2) Interpolate PTRS estimated value in TD after all PTRS symbols + * 3) Compensate signal with PTRS estimation for slot + *********************************************************************/ +void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, + NR_UE_PDSCH **pdsch_vars, + NR_DL_FRAME_PARMS *frame_parms, + NR_DL_UE_HARQ_t *dlsch0_harq, + NR_DL_UE_HARQ_t *dlsch1_harq, + uint8_t eNB_id, + uint8_t nr_slot_rx, + unsigned char symbol, + uint32_t nb_re_pdsch, + unsigned char harq_pid, + uint16_t rnti, + RX_type_t rx_type) +{ + //#define DEBUG_DL_PTRS 1 + int16_t *phase_per_symbol = NULL; + int32_t *ptrs_re_symbol = NULL; + int8_t ret = 0; + /* harq specific variables */ + uint8_t symbInSlot = 0; + uint16_t *startSymbIndex = NULL; + uint16_t *nbSymb = NULL; + uint8_t *L_ptrs = NULL; + uint8_t *K_ptrs = NULL; + uint16_t *dmrsSymbPos = NULL; + uint16_t *ptrsSymbPos = NULL; + uint8_t *ptrsSymbIdx = NULL; + uint8_t *ptrsReOffset = NULL; + uint8_t *dmrsConfigType = NULL; + uint16_t *nb_rb = NULL; + + if(dlsch0_harq->status == ACTIVE) { + symbInSlot = dlsch0_harq->start_symbol + dlsch0_harq->nb_symbols; + startSymbIndex = &dlsch0_harq->start_symbol; + nbSymb = &dlsch0_harq->nb_symbols; + L_ptrs = &dlsch0_harq->PTRSTimeDensity; + K_ptrs = &dlsch0_harq->PTRSFreqDensity; + dmrsSymbPos = &dlsch0_harq->dlDmrsSymbPos; + ptrsSymbPos = &dlsch0_harq->ptrs_symbols; + ptrsSymbIdx = &dlsch0_harq->ptrs_symbol_index; + ptrsReOffset = &dlsch0_harq->PTRSReOffset; + dmrsConfigType = &dlsch0_harq->ptrs_symbol_index; + nb_rb = &dlsch0_harq->nb_rb; + } + if(dlsch1_harq) { + symbInSlot = dlsch1_harq->start_symbol + dlsch0_harq->nb_symbols; + startSymbIndex = &dlsch1_harq->start_symbol; + nbSymb = &dlsch1_harq->nb_symbols; + L_ptrs = &dlsch1_harq->PTRSTimeDensity; + K_ptrs = &dlsch1_harq->PTRSFreqDensity; + dmrsSymbPos = &dlsch1_harq->dlDmrsSymbPos; + ptrsSymbPos = &dlsch1_harq->ptrs_symbols; + ptrsSymbIdx = &dlsch1_harq->ptrs_symbol_index; + ptrsReOffset = &dlsch1_harq->PTRSReOffset; + dmrsConfigType = &dlsch1_harq->ptrs_symbol_index; + nb_rb = &dlsch1_harq->nb_rb; + } + /* loop over antennas */ + for (int aarx=0; aarxnb_antennas_rx; aarx++) { + phase_per_symbol = (int16_t*)pdsch_vars[eNB_id]->ptrs_phase_per_slot[aarx]; + ptrs_re_symbol = (int32_t*)pdsch_vars[eNB_id]->ptrs_re_per_slot[aarx]; + ptrs_re_symbol[symbol] = 0; + phase_per_symbol[(2*symbol)+1] = 0; // Imag + /* set DMRS estimates to 0 angle with magnitude 1 */ + if(is_dmrs_symbol(symbol,*dmrsSymbPos)) { + /* set DMRS real estimation to 32767 */ + phase_per_symbol[2*symbol]=(int16_t)((1<<15)-1); // 32767 +#ifdef DEBUG_DL_PTRS + printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[2*symbol],phase_per_symbol[(2*symbol)+1]); +#endif + } + else { // real ptrs value is set to 0 + phase_per_symbol[2*symbol] = 0; // Real + } + + if(dlsch0_harq->status == ACTIVE) { + if(symbol == *startSymbIndex) { + *ptrsSymbPos = 0; + set_ptrs_symb_idx(ptrsSymbPos, + *nbSymb, + *startSymbIndex, + 1<< *L_ptrs, + *dmrsSymbPos); + } + /* if not PTRS symbol set current ptrs symbol index to zero*/ + *ptrsSymbIdx = 0; + /* Check if current symbol contains PTRS */ + if(is_ptrs_symbol(symbol, *ptrsSymbPos)) { + *ptrsSymbIdx = symbol; + /*------------------------------------------------------------------------------------------------------- */ + /* 1) Estimate common phase error per PTRS symbol */ + /*------------------------------------------------------------------------------------------------------- */ + nr_ptrs_cpe_estimation(*K_ptrs,*ptrsReOffset,*dmrsConfigType,*nb_rb, + rnti, + (int16_t *)&pdsch_vars[eNB_id]->dl_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pdsch], + nr_slot_rx, + symbol,frame_parms->ofdm_symbol_size, + (int16_t*)&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(symbol * nb_re_pdsch)], + ue->nr_gold_pdsch[eNB_id][nr_slot_rx][symbol], + &phase_per_symbol[2* symbol], + &ptrs_re_symbol[symbol]); + } + }// HARQ 0 + + /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/ + if(symbol == (symbInSlot -1)) { + /*------------------------------------------------------------------------------------------------------- */ + /* 2) Interpolate PTRS estimated value in TD */ + /*------------------------------------------------------------------------------------------------------- */ + /* If L-PTRS is > 0 then we need interpolation */ + if(*L_ptrs > 0) { + ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb); + if(ret != 0) { + LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); + } + } +#ifdef DEBUG_DL_PTRS + LOG_M("ptrsEst.m","est",pdsch_vars[eNB_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 ); + LOG_M("rxdataF_bf_ptrs_comp.m","bf_ptrs_cmp", + &pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(*startSymbIndex) * NR_NB_SC_PER_RB * (*nb_rb) ], + (*nb_rb) * NR_NB_SC_PER_RB * (*nbSymb),1,1); +#endif + /*------------------------------------------------------------------------------------------------------- */ + /* 3) Compensated DMRS based estimated signal with PTRS estimation */ + /*--------------------------------------------------------------------------------------------------------*/ + for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++) { + /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */ + /* Skip rotation if the slot processing is wrong */ + if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) { +#ifdef DEBUG_DL_PTRS + printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]); +#endif + rotate_cpx_vector((int16_t*)&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], + &phase_per_symbol[2* i], + (int16_t*)&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], + ((*nb_rb) * NR_NB_SC_PER_RB), 15); + }// if not DMRS Symbol + }// symbol loop + }// last symbol check + }//Antenna loop +}//main function diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 74168cb671..419f84d418 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -103,6 +103,18 @@ void phy_adjust_gain_nr(PHY_VARS_NR_UE *ue, int16_t get_nr_PL(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index); +void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, + NR_UE_PDSCH **pdsch_vars, + NR_DL_FRAME_PARMS *frame_parms, + NR_DL_UE_HARQ_t *dlsch0_harq, + NR_DL_UE_HARQ_t *dlsch1_harq, + uint8_t eNB_id, + uint8_t nr_slot_rx, + unsigned char symbol, + uint32_t nb_re_pdsch, + unsigned char harq_pid, + uint16_t rnti, + RX_type_t rx_type); float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 4757872c28..971db724c6 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -243,7 +243,7 @@ void nr_ue_rsrp_measurements(PHY_VARS_NR_UE *ue, unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size; - symbol_offset = ue->frame_parms.ofdm_symbol_size*(ue->symbol_offset+1); + symbol_offset = ue->frame_parms.ofdm_symbol_size*((ue->symbol_offset+1)%(ue->frame_parms.symbols_per_slot)); ue->measurements.rsrp[eNB_offset] = 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 9bfc11d64a..5e45b90536 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -373,7 +373,10 @@ void nr_pdcch_extract_rbs_single(int32_t **rxdataF, for (int rb=0;rb>3] & (1<<(c_rb_by6&7))) == 0) c_rb+=6; + while ((coreset_freq_dom[c_rb_by6>>3] & (1<<(7-(c_rb_by6&7)))) == 0) { + c_rb+=6; + c_rb_by6 = c_rb/6; + } LOG_DDD("c_rb=%d\n",c_rb); rxF=NULL; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 61d6c72ddf..75cb6ff91b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -279,7 +279,6 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; } uint16_t dmrs_length = get_num_dmrs(harq_process->dlDmrsSymbPos); - AssertFatal(dmrs_length == 1 || dmrs_length == 2,"Illegal dmrs_length %d\n",dmrs_length); uint32_t i,j; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 51e34e0c89..8e6fed864c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -37,7 +37,10 @@ //#include "extern.h" #include "PHY/sse_intrin.h" #include "T.h" +#include "openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h" +#include "PHY/NR_REFSIG/nr_refsig.h" +#include "PHY/NR_REFSIG/dmrs_nr.h" #ifndef USER_MODE #define NOCYGWIN_STATIC static @@ -99,6 +102,29 @@ static void nr_dlsch_layer_demapping(int16_t **llr_cw, uint16_t length, int16_t **llr_layers); + +/* compute LLR */ +static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, + NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp_ptr, + int32_t **dl_ch_mag_ptr, + NR_DL_UE_HARQ_t *dlsch0_harq, + NR_DL_UE_HARQ_t *dlsch1_harq, + RX_type_t rx_type, + unsigned char harq_pid, + unsigned char eNB_id, + unsigned char eNB_id_i, + unsigned char first_symbol_flag, + unsigned char symbol, + unsigned short nb_rb, + unsigned short round, + int32_t codeword_TB0, + int32_t codeword_TB1, + uint32_t len, + uint8_t nr_slot_rx, + uint8_t beamforming_mode); + +/* Main Function */ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, PDSCH_t type, @@ -143,19 +169,17 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, //to be updated higher layer unsigned short start_rb = 0; unsigned short nb_rb_pdsch = 50; - int16_t *pllr_symbol_cw0; - int16_t *pllr_symbol_cw1; - int16_t *pllr_symbol_layer0; - int16_t *pllr_symbol_layer1; //int16_t *pllr_symbol_cw0_deint; //int16_t *pllr_symbol_cw1_deint; - uint32_t llr_offset_symbol; //uint16_t bundle_L = 2; uint8_t pilots=0; uint8_t config_type = ue->dmrs_DownlinkConfig.pdsch_dmrs_type; uint16_t n_tx=1, n_rx=1; int32_t median[16]; uint32_t len; + uint16_t startSymbIdx=0; + uint16_t nbSymb=0; + uint16_t pduBitmap=0x0; switch (type) { case SI_PDSCH: @@ -384,7 +408,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, nb_rb_pdsch, nr_slot_rx, ue->high_speed_flag, - frame_parms); + frame_parms, + dlsch0_harq->dlDmrsSymbPos); } /*else if(beamforming_mode>7) { LOG_W(PHY,"dlsch_demodulation: beamforming mode not supported yet.\n"); @@ -521,6 +546,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, pdsch_vars[eNB_id]->dl_ch_estimates_ext, pdsch_vars[eNB_id]->dl_ch_mag0, pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->dl_ch_magr0, pdsch_vars[eNB_id]->rxdataF_comp0, (aatx>1) ? pdsch_vars[eNB_id]->rho : NULL, frame_parms, @@ -673,376 +699,66 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, start_meas(&ue->generic_stat_bis[proc->thread_id][slot]); #endif - //printf("LLR dlsch0_harq->Qm %d rx_type %d cw0 %d cw1 %d symbol %d \n",dlsch0_harq->Qm,rx_type,codeword_TB0,codeword_TB1,symbol); - // compute LLRs - // -> // compute @pointer where llrs should filled for this ofdm-symbol + /* Store the valid DL RE's */ + pdsch_vars[eNB_id]->dl_valid_re[symbol-1] = len; - if (first_symbol_flag==1) pdsch_vars[eNB_id]->llr_offset[symbol-1] = 0; - llr_offset_symbol = pdsch_vars[eNB_id]->llr_offset[symbol-1]; - //pllr_symbol_cw0_deint = (int8_t*)pdsch_vars[eNB_id]->llr[0]; - //pllr_symbol_cw1_deint = (int8_t*)pdsch_vars[eNB_id]->llr[1]; - pllr_symbol_layer0 = pdsch_vars[eNB_id]->layer_llr[0]; - pllr_symbol_layer1 = pdsch_vars[eNB_id]->layer_llr[1]; - pllr_symbol_layer0 += llr_offset_symbol; - pllr_symbol_layer1 += llr_offset_symbol; - pllr_symbol_cw0 = pdsch_vars[eNB_id]->llr[0]; - pllr_symbol_cw1 = pdsch_vars[eNB_id]->llr[1]; - pllr_symbol_cw0 += llr_offset_symbol; - pllr_symbol_cw1 += llr_offset_symbol; - - pdsch_vars[eNB_id]->llr_offset[symbol] = len*dlsch0_harq->Qm + llr_offset_symbol; - - LOG_D(PHY,"compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d energy %d\n", - symbol, - nb_rb,dlsch0_harq->Qm, - pdsch_vars[eNB_id]->llr_length[symbol], - pdsch_vars[eNB_id]->llr_offset[symbol], - signal_energy(pdsch_vars[eNB_id]->rxdataF_comp0[0], 7*2*frame_parms->N_RB_DL*12)); - - - /*printf("compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %p @LLR Buff(symb) %p\n", - symbol, - nb_rb,dlsch0_harq->Qm, - pdsch_vars[eNB_id]->llr_length[symbol], - pdsch_vars[eNB_id]->llr_offset[symbol], - pdsch_vars[eNB_id]->llr[0], - pllr_symbol_cw0);*/ - - switch (dlsch0_harq->Qm) { - case 2 : - if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { - nr_dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw0, - symbol, - len, - first_symbol_flag, - nb_rb, - beamforming_mode); - - } else if (codeword_TB0 == -1){ - - nr_dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw1, - symbol, - len, - first_symbol_flag, - nb_rb, - beamforming_mode); + if(dlsch0_harq->status == ACTIVE) { + startSymbIdx = dlsch0_harq->start_symbol; + nbSymb = dlsch0_harq->nb_symbols; + pduBitmap = dlsch0_harq->pduBitmap; } - else if (rx_type >= rx_IC_single_stream) { - if (dlsch1_harq->Qm == 2) { - nr_dlsch_qpsk_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_qpsk_qpsk_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else if (dlsch1_harq->Qm == 4) { - nr_dlsch_qpsk_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_16qam_qpsk_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } + if(dlsch1_harq) { + startSymbIdx = dlsch1_harq->start_symbol; + nbSymb = dlsch1_harq->nb_symbols; + pduBitmap = dlsch1_harq->pduBitmap; + } + + /* Check for PTRS bitmap and process it respectively */ + if((pduBitmap & 0x1) && (type == PDSCH)) { + nr_pdsch_ptrs_processing(ue, + pdsch_vars, + frame_parms, + dlsch0_harq, dlsch1_harq, + eNB_id, nr_slot_rx, + symbol, (nb_rb*12), + harq_pid, + dlsch[0]->rnti,rx_type); + pdsch_vars[eNB_id]->dl_valid_re[symbol-1] -= pdsch_vars[eNB_id]->ptrs_re_per_slot[0][symbol]; + } + + /* at last symbol in a slot calculate LLR's for whole slot */ + if(symbol == (startSymbIdx + nbSymb -1)) { + for(uint8_t i =startSymbIdx; i <= nbSymb;i++) { + /* re evaluating the first symbol flag as LLR's are done in symbol loop */ + if(i == startSymbIdx && i < 3) { + first_symbol_flag =1; } else { - nr_dlsch_qpsk_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_64qam_qpsk_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - } - break; - case 4 : - if ((rx_type==rx_standard ) || (codeword_TB1 == -1)) { - nr_dlsch_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], - pdsch_vars[eNB_id]->dl_ch_mag0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr128, - beamforming_mode); - } else if (codeword_TB0 == -1){ - nr_dlsch_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[1], - pdsch_vars[eNB_id]->dl_ch_mag0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr128_2ndstream, - beamforming_mode); - } - else if (rx_type >= rx_IC_single_stream) { - if (dlsch1_harq->Qm == 2) { - nr_dlsch_16qam_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_qpsk_16qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else if (dlsch1_harq->Qm == 4) { - nr_dlsch_16qam_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_16qam_16qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else { - nr_dlsch_16qam_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_64qam_16qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0, - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); + first_symbol_flag=0; } + /* Calculate LLR's for each symbol */ + nr_dlsch_llr(pdsch_vars, frame_parms, + rxdataF_comp_ptr, dl_ch_mag_ptr, + dlsch0_harq, dlsch1_harq, + rx_type, harq_pid, + eNB_id, eNB_id_i, + first_symbol_flag, + i, nb_rb, round, + codeword_TB0, codeword_TB1, + pdsch_vars[eNB_id]->dl_valid_re[i-1], + nr_slot_rx, beamforming_mode); } } - break; - case 6 : - if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { - nr_dlsch_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - (int16_t*)pllr_symbol_cw0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], - beamforming_mode); - } else if (codeword_TB0 == -1){ - nr_dlsch_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw1, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], - beamforming_mode); - } - else if (rx_type >= rx_IC_single_stream) { - if (dlsch1_harq->Qm == 2) { - nr_dlsch_64qam_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_qpsk_64qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else if (dlsch1_harq->Qm == 4) { - nr_dlsch_64qam_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - pdsch_vars[eNB_id]->layer_llr[0], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_16qam_64qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pdsch_vars[eNB_id]->layer_llr[1], - symbol,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr128_2ndstream); - } - } - else { - nr_dlsch_64qam_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - rxdataF_comp_ptr,//i - pdsch_vars[eNB_id]->dl_ch_mag0, - dl_ch_mag_ptr,//i - pdsch_vars[eNB_id]->dl_ch_rho2_ext, - (int16_t*)pllr_symbol_layer0, - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr_offset[symbol]); - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_64qam_64qam_llr(frame_parms, - rxdataF_comp_ptr, - pdsch_vars[eNB_id]->rxdataF_comp0,//i - dl_ch_mag_ptr, - pdsch_vars[eNB_id]->dl_ch_mag0,//i - pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], - pllr_symbol_layer1, - symbol,len,first_symbol_flag,nb_rb, - adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol), - pdsch_vars[eNB_id]->llr_offset[symbol]); - } - } - } - break; - default: - LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); - return(-1); - break; - } - - if (dlsch1_harq) { - uint8_t Qm = nr_get_Qm_dl(dlsch1_harq->mcs,dlsch1_harq->mcs_table); - if (Qm == 0){ - LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n"); - return -1; - } - switch (Qm) { - case 2 : - if (rx_type==rx_standard) { - nr_dlsch_qpsk_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw0, - symbol,len,first_symbol_flag,nb_rb, - beamforming_mode); - } - break; - case 4: - if (rx_type==rx_standard) { - nr_dlsch_16qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pdsch_vars[eNB_id]->llr[0], - pdsch_vars[eNB_id]->dl_ch_mag0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr128, - beamforming_mode); - } - break; - case 6 : - if (rx_type==rx_standard) { - nr_dlsch_64qam_llr(frame_parms, - pdsch_vars[eNB_id]->rxdataF_comp0, - pllr_symbol_cw0, - pdsch_vars[eNB_id]->dl_ch_mag0, - pdsch_vars[eNB_id]->dl_ch_magb0, - symbol,len,first_symbol_flag,nb_rb, - pdsch_vars[eNB_id]->llr_offset[symbol], - beamforming_mode); - } - break; - default: - LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); - return(-1); - break; - } - } //nr_dlsch_deinterleaving(symbol,bundle_L,(int16_t*)pllr_symbol_cw0,(int16_t*)pllr_symbol_cw0_deint, nb_rb_pdsch); - - if (rx_type==rx_IC_dual_stream) { - nr_dlsch_layer_demapping(pdsch_vars[eNB_id]->llr, - dlsch[0]->harq_processes[harq_pid]->Nl, - dlsch[0]->harq_processes[harq_pid]->Qm, - dlsch[0]->harq_processes[harq_pid]->G, - pdsch_vars[eNB_id]->layer_llr); - } + + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_layer_demapping(pdsch_vars[eNB_id]->llr, + dlsch[0]->harq_processes[harq_pid]->Nl, + dlsch[0]->harq_processes[harq_pid]->Qm, + dlsch[0]->harq_processes[harq_pid]->G, + pdsch_vars[eNB_id]->layer_llr); + } #if UE_TIMING_TRACE stop_meas(&ue->generic_stat_bis[proc->thread_id][slot]); @@ -1145,6 +861,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, int **dl_ch_estimates_ext, int **dl_ch_mag, int **dl_ch_magb, + int **dl_ch_magr, int **rxdataF_comp, int **rho, NR_DL_FRAME_PARMS *frame_parms, @@ -1161,17 +878,23 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, unsigned short rb; unsigned char aatx,aarx; - __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; - __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b; + __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*dl_ch_mag128r,*rxdataF128,*rxdataF_comp128,*rho128; + __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b,QAM_amp128r; QAM_amp128b = _mm_setzero_si128(); for (aatx=0; aatxnb_antenna_ports_gNB; aatx++) { if (mod_order == 4) { QAM_amp128 = _mm_set1_epi16(QAM16_n1); // 2/sqrt(10) QAM_amp128b = _mm_setzero_si128(); + QAM_amp128r = _mm_setzero_si128(); } else if (mod_order == 6) { QAM_amp128 = _mm_set1_epi16(QAM64_n1); // QAM_amp128b = _mm_set1_epi16(QAM64_n2); + QAM_amp128r = _mm_setzero_si128(); + } else if (mod_order == 8) { + QAM_amp128 = _mm_set1_epi16(QAM256_n1); + QAM_amp128b = _mm_set1_epi16(QAM256_n2); + QAM_amp128r = _mm_set1_epi16(QAM256_n3); } // printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol); @@ -1181,6 +904,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*nb_rb*12]; dl_ch_mag128 = (__m128i *)&dl_ch_mag[(aatx<<1)+aarx][symbol*nb_rb*12]; dl_ch_mag128b = (__m128i *)&dl_ch_magb[(aatx<<1)+aarx][symbol*nb_rb*12]; + dl_ch_mag128r = (__m128i *)&dl_ch_magr[(aatx<<1)+aarx][symbol*nb_rb*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*nb_rb*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*nb_rb*12]; @@ -1201,6 +925,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, dl_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[0] = dl_ch_mag128[0]; + dl_ch_mag128r[0] = dl_ch_mag128[0]; dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1); //print_ints("Re(ch):",(int16_t*)&mmtmpD0); @@ -1208,6 +933,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, //print_shorts("mag:",(int16_t*)&dl_ch_mag128[0]); dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[1] = dl_ch_mag128[1]; + dl_ch_mag128r[1] = dl_ch_mag128[1]; dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128); dl_ch_mag128[1] = _mm_slli_epi16(dl_ch_mag128[1],1); @@ -1218,6 +944,7 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, dl_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1); dl_ch_mag128b[2] = dl_ch_mag128[2]; + dl_ch_mag128r[2] = dl_ch_mag128[2]; dl_ch_mag128[2] = _mm_mulhi_epi16(dl_ch_mag128[2],QAM_amp128); dl_ch_mag128[2] = _mm_slli_epi16(dl_ch_mag128[2],1); @@ -1230,9 +957,18 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, dl_ch_mag128b[1] = _mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b); dl_ch_mag128b[1] = _mm_slli_epi16(dl_ch_mag128b[1],1); + dl_ch_mag128r[0] = _mm_mulhi_epi16(dl_ch_mag128r[0],QAM_amp128r); + dl_ch_mag128r[0] = _mm_slli_epi16(dl_ch_mag128r[0],1); + + dl_ch_mag128r[1] = _mm_mulhi_epi16(dl_ch_mag128r[1],QAM_amp128r); + dl_ch_mag128r[1] = _mm_slli_epi16(dl_ch_mag128r[1],1); + if (pilots==0) { dl_ch_mag128b[2] = _mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b); dl_ch_mag128b[2] = _mm_slli_epi16(dl_ch_mag128b[2],1); + + dl_ch_mag128r[2] = _mm_mulhi_epi16(dl_ch_mag128r[2],QAM_amp128r); + dl_ch_mag128r[2] = _mm_slli_epi16(dl_ch_mag128r[2],1); } } @@ -1300,12 +1036,14 @@ void nr_dlsch_channel_compensation(int **rxdataF_ext, dl_ch128+=3; dl_ch_mag128+=3; dl_ch_mag128b+=3; + dl_ch_mag128r+=3; rxdataF128+=3; rxdataF_comp128+=3; } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less dl_ch128+=2; dl_ch_mag128+=2; dl_ch_mag128b+=2; + dl_ch_mag128r+=2; rxdataF128+=2; rxdataF_comp128+=2; } @@ -2367,7 +2105,8 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF, unsigned short nb_rb_pdsch, unsigned char nr_slot_rx, uint32_t high_speed_flag, - NR_DL_FRAME_PARMS *frame_parms) { + NR_DL_FRAME_PARMS *frame_parms, + uint16_t dlDmrsSymbPos) { @@ -2375,7 +2114,7 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF, unsigned char i,aarx; //,nsymb,sss_symb,pss_symb=0,l; int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; - + int8_t validDmrsEst = 0; //store last DMRS Symbol index unsigned char j=0; @@ -2390,10 +2129,9 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF, k = frame_parms->first_carrier_offset + NR_NB_SC_PER_RB*start_rb; - if (high_speed_flag == 1) - dl_ch0 = &dl_ch_estimates[aarx][(2*(frame_parms->ofdm_symbol_size))]; - else - dl_ch0 = &dl_ch_estimates[aarx][0]; + validDmrsEst = get_valid_dmrs_idx_for_channel_est(dlDmrsSymbPos,symbol); + + dl_ch0 = &dl_ch_estimates[aarx][(validDmrsEst*(frame_parms->ofdm_symbol_size))]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(nb_rb_pdsch*12)]; @@ -2572,6 +2310,423 @@ static void nr_dlsch_layer_demapping(int16_t **llr_cw, AssertFatal(0, "Not supported number of layers %d\n", Nl); } } + +static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars, + NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp_ptr, + int32_t **dl_ch_mag_ptr, + NR_DL_UE_HARQ_t *dlsch0_harq, + NR_DL_UE_HARQ_t *dlsch1_harq, + RX_type_t rx_type, + unsigned char harq_pid, + unsigned char eNB_id, + unsigned char eNB_id_i, + unsigned char first_symbol_flag, + unsigned char symbol, + unsigned short nb_rb, + unsigned short round, + int32_t codeword_TB0, + int32_t codeword_TB1, + uint32_t len, + uint8_t nr_slot_rx, + uint8_t beamforming_mode) +{ + + int16_t *pllr_symbol_cw0; + int16_t *pllr_symbol_cw1; + int16_t *pllr_symbol_layer0; + int16_t *pllr_symbol_layer1; + uint32_t llr_offset_symbol; + + if (first_symbol_flag==1) pdsch_vars[eNB_id]->llr_offset[symbol-1] = 0; + llr_offset_symbol = pdsch_vars[eNB_id]->llr_offset[symbol-1]; + //pllr_symbol_cw0_deint = (int8_t*)pdsch_vars[eNB_id]->llr[0]; + //pllr_symbol_cw1_deint = (int8_t*)pdsch_vars[eNB_id]->llr[1]; + pllr_symbol_layer0 = pdsch_vars[eNB_id]->layer_llr[0]; + pllr_symbol_layer1 = pdsch_vars[eNB_id]->layer_llr[1]; + pllr_symbol_layer0 += llr_offset_symbol; + pllr_symbol_layer1 += llr_offset_symbol; + pllr_symbol_cw0 = pdsch_vars[eNB_id]->llr[0]; + pllr_symbol_cw1 = pdsch_vars[eNB_id]->llr[1]; + pllr_symbol_cw0 += llr_offset_symbol; + pllr_symbol_cw1 += llr_offset_symbol; + + pdsch_vars[eNB_id]->llr_offset[symbol] = len*dlsch0_harq->Qm + llr_offset_symbol; + + /*LOG_I(PHY,"compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %x @LLR Buff(symb) %x\n", + symbol, + nb_rb,dlsch0_harq->Qm, + pdsch_vars[eNB_id]->llr_length[symbol], + pdsch_vars[eNB_id]->llr_offset[symbol], + (int16_t*)pdsch_vars[eNB_id]->llr[0], + pllr_symbol_cw0);*/ + + /*printf("compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %p @LLR Buff(symb) %p\n", + symbol, + nb_rb,dlsch0_harq->Qm, + pdsch_vars[eNB_id]->llr_length[symbol], + pdsch_vars[eNB_id]->llr_offset[symbol], + pdsch_vars[eNB_id]->llr[0], + pllr_symbol_cw0);*/ + + switch (dlsch0_harq->Qm) { + case 2 : + if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { + nr_dlsch_qpsk_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pllr_symbol_cw0, + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + + } else if (codeword_TB0 == -1){ + + nr_dlsch_qpsk_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pllr_symbol_cw1, + symbol, + len, + first_symbol_flag, + nb_rb, + beamforming_mode); + } + else if (rx_type >= rx_IC_single_stream) { + if (dlsch1_harq->Qm == 2) { + nr_dlsch_qpsk_qpsk_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->layer_llr[0], + symbol,len,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_qpsk_qpsk_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->layer_llr[1], + symbol,len,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else if (dlsch1_harq->Qm == 4) { + nr_dlsch_qpsk_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->layer_llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_16qam_qpsk_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->layer_llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else { + nr_dlsch_qpsk_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->layer_llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_64qam_qpsk_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->layer_llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + } + break; + case 4 : + if ((rx_type==rx_standard ) || (codeword_TB1 == -1)) { + nr_dlsch_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->dl_ch_mag0, + symbol,len,first_symbol_flag,nb_rb, + pdsch_vars[eNB_id]->llr128, + beamforming_mode); + } else if (codeword_TB0 == -1){ + nr_dlsch_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[1], + pdsch_vars[eNB_id]->dl_ch_mag0, + symbol,len,first_symbol_flag,nb_rb, + pdsch_vars[eNB_id]->llr128_2ndstream, + beamforming_mode); + } + else if (rx_type >= rx_IC_single_stream) { + if (dlsch1_harq->Qm == 2) { + nr_dlsch_16qam_qpsk_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->layer_llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_qpsk_16qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + pdsch_vars[eNB_id]->dl_ch_mag0,//i + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->layer_llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else if (dlsch1_harq->Qm == 4) { + nr_dlsch_16qam_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->layer_llr[0], + symbol,len,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_16qam_16qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_mag0,//i + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->layer_llr[1], + symbol,len,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else { + nr_dlsch_16qam_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->layer_llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_64qam_16qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0, + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->layer_llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + } + break; + case 6 : + if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { + nr_dlsch_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + (int16_t*)pllr_symbol_cw0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + symbol,len,first_symbol_flag,nb_rb, + pdsch_vars[eNB_id]->llr_offset[symbol], + beamforming_mode); + } else if (codeword_TB0 == -1){ + nr_dlsch_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pllr_symbol_cw1, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + symbol,len,first_symbol_flag,nb_rb, + pdsch_vars[eNB_id]->llr_offset[symbol], + beamforming_mode); + } + else if (rx_type >= rx_IC_single_stream) { + if (dlsch1_harq->Qm == 2) { + nr_dlsch_64qam_qpsk_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->layer_llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_qpsk_64qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->layer_llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else if (dlsch1_harq->Qm == 4) { + nr_dlsch_64qam_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + pdsch_vars[eNB_id]->layer_llr[0], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128); + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_16qam_64qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_mag0,//i + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pdsch_vars[eNB_id]->layer_llr[1], + symbol,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr128_2ndstream); + } + } + else { + nr_dlsch_64qam_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + rxdataF_comp_ptr,//i + pdsch_vars[eNB_id]->dl_ch_mag0, + dl_ch_mag_ptr,//i + pdsch_vars[eNB_id]->dl_ch_rho2_ext, + (int16_t*)pllr_symbol_layer0, + symbol,len,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr_offset[symbol]); + if (rx_type==rx_IC_dual_stream) { + nr_dlsch_64qam_64qam_llr(frame_parms, + rxdataF_comp_ptr, + pdsch_vars[eNB_id]->rxdataF_comp0,//i + dl_ch_mag_ptr, + pdsch_vars[eNB_id]->dl_ch_mag0,//i + pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round], + pllr_symbol_layer1, + symbol,len,first_symbol_flag,nb_rb, + adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol), + pdsch_vars[eNB_id]->llr_offset[symbol]); + } + } + } + break; + case 8: + if ((rx_type==rx_standard) || (codeword_TB1 == -1)) { + nr_dlsch_256qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + (int16_t*)pllr_symbol_cw0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->dl_ch_magr0, + symbol,len,first_symbol_flag,nb_rb, + pdsch_vars[eNB_id]->llr_offset[symbol], + beamforming_mode); + } else if (codeword_TB0 == -1){ + nr_dlsch_256qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pllr_symbol_cw1, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->dl_ch_magr0, + symbol,len,first_symbol_flag,nb_rb, + pdsch_vars[eNB_id]->llr_offset[symbol], + beamforming_mode); + } + break; + default: + LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); + return(-1); + break; + } + + if (dlsch1_harq) { + switch (nr_get_Qm_dl(dlsch1_harq->mcs,dlsch1_harq->mcs_table)) { + case 2 : + if (rx_type==rx_standard) { + nr_dlsch_qpsk_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pllr_symbol_cw0, + symbol,len,first_symbol_flag,nb_rb, + beamforming_mode); + } + break; + case 4: + if (rx_type==rx_standard) { + nr_dlsch_16qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pdsch_vars[eNB_id]->llr[0], + pdsch_vars[eNB_id]->dl_ch_mag0, + symbol,len,first_symbol_flag,nb_rb, + pdsch_vars[eNB_id]->llr128, + beamforming_mode); + } + break; + case 6 : + if (rx_type==rx_standard) { + nr_dlsch_64qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pllr_symbol_cw0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + symbol,len,first_symbol_flag,nb_rb, + pdsch_vars[eNB_id]->llr_offset[symbol], + beamforming_mode); + } + break; + case 8 : + if (rx_type==rx_standard) { + nr_dlsch_256qam_llr(frame_parms, + pdsch_vars[eNB_id]->rxdataF_comp0, + pllr_symbol_cw0, + pdsch_vars[eNB_id]->dl_ch_mag0, + pdsch_vars[eNB_id]->dl_ch_magb0, + pdsch_vars[eNB_id]->dl_ch_magr0, + symbol,len,first_symbol_flag,nb_rb, + pdsch_vars[eNB_id]->llr_offset[symbol], + beamforming_mode); + } + break; + default: + LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n"); + return(-1); + break; + } + } + return 0; +} //============================================================================================== #ifdef USER_MODE diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c index e0b24a033a..68a206e7c7 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_llr_computation.c @@ -1089,6 +1089,108 @@ void nr_dlsch_64qam_llr_SIC(NR_DL_FRAME_PARMS *frame_parms, } } //#endif + +//---------------------------------------------------------------------------------------------- +// 256-QAM +//---------------------------------------------------------------------------------------------- + +void nr_dlsch_256qam_llr(NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int16_t *dlsch_llr, + int32_t **dl_ch_mag, + int32_t **dl_ch_magb, + int32_t **dl_ch_magr, + uint8_t symbol, + uint32_t len, + uint8_t first_symbol_flag, + uint16_t nb_rb, + uint32_t llr_offset, + uint8_t beamforming_mode) +{ + __m128i *rxF = (__m128i*)&rxdataF_comp[0][(symbol*nb_rb*12)]; + __m128i *ch_mag,*ch_magb,*ch_magr; + + int i,len2; + unsigned char len_mod4; + short *llr; + int16_t *llr2; + int8_t *pllr_symbol; + + /* + if (first_symbol_flag==1) + llr = dlsch_llr; + else + llr = *llr_save; + */ + llr = dlsch_llr; + + pllr_symbol = (int8_t*)dlsch_llr; + pllr_symbol += llr_offset; + + ch_mag = (__m128i*)&dl_ch_mag[0][(symbol*nb_rb*12)]; + ch_magb = (__m128i*)&dl_ch_magb[0][(symbol*nb_rb*12)]; + ch_magr = (__m128i*)&dl_ch_magr[0][(symbol*nb_rb*12)]; + llr2 = llr; + llr += (len*8); + + len_mod4 =len&3; + len2=len>>2; // length in quad words (4 REs) + len2+=((len_mod4==0)?0:1); + + for (i=0; isymbol_offset // computing the offset wrt the beginning of the frame - sync_pos_frame = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)+((ue->symbol_offset)-1)*(fp->ofdm_symbol_size + fp->nb_prefix_samples); - + int mu = fp->numerology_index; + // number of symbols with different prefix length + // every 7*(1<symbol_offset/(7*(1<ofdm_symbol_size + fp->nb_prefix_samples0)+(ue->symbol_offset-n_symb_prefix0)*(fp->ofdm_symbol_size + fp->nb_prefix_samples); if (ue->ssb_offset < sync_pos_frame) ue->rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset; else diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 813e737563..4d21fe782b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -62,7 +62,7 @@ uint16_t nr_pbch_extract(int **rxdataF, unsigned int rx_offset = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; //and // if (rx_offset>= frame_parms->ofdm_symbol_size) rx_offset-=frame_parms->ofdm_symbol_size; - rx_offset=(rx_offset)%(frame_parms->ofdm_symbol_size); + rx_offset=(rx_offset)%(frame_parms->ofdm_symbol_size); AssertFatal(symbol>=1 && symbol<5, "symbol %d illegal for PBCH extraction\n", @@ -538,6 +538,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, M = NR_POLAR_PBCH_E; nushift = (Lmax==4)? i_ssb&3 : i_ssb&7; uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041; + nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_E,0,0); //polar decoding de-rate matching const t_nrPolar_params *currentPtr = nr_polar_params( NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL,1,&ue->polarList); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 465598d468..3ab88dac0a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -105,6 +105,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1)); prach_start = fp->get_samples_slot_timestamp(slot, fp, 0) + sample_offset_slot; + //printf("prachstartsymbold %d, sample_offset_slot %d, prach_start %d\n",prachStartSymbol, sample_offset_slot, prach_start); + // First compute physical root sequence /************************************************************************ * 4G and NR NCS tables are slightly different and depend on prach format @@ -241,6 +243,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ * *********************************************************/ + if (mu==1) { if (fp->N_RB_UL <= 100) AssertFatal(1 == 0, "N_RB_UL %d not support for NR PRACH yet\n", fp->N_RB_UL); else if (fp->N_RB_UL < 137) { @@ -321,6 +324,22 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } } } + } + else if (mu==3) { + if (fp->threequarter_fs) + AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu); + + if (prach_sequence_length == 0) + AssertFatal(1==0,"long prach not supported for numerology %d\n",mu); + + if (fp->N_RB_UL == 32) + dftlen=512; + else if (fp->N_RB_UL == 66) + dftlen=1024; + else + AssertFatal(1==0,"N_RB_UL %d not support for numerology %d\n",fp->N_RB_UL,mu); + } + for (offset=0,offset2=0; offsetN_RB_UL <= 100) - AssertFatal(1==0,"N_RB_UL %d not supported for NR PRACH yet\n",fp->N_RB_UL); + //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 + uint8_t use_extended_prach_prefix = 0; + if(fp->numerology_index == 0) { + if (prachStartSymbol == 0 || prachStartSymbol == 7) + use_extended_prach_prefix = 1; + } + else { + if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0) + use_extended_prach_prefix = 1; + } + + if (fp->N_RB_UL <= 34) { //32 PRB case 61.44Msps + if (fp->threequarter_fs == 0) { + Ncp<<=1; //to account for 61.44Mbps + // This is after cyclic prefix + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_sequence_length == 0) + AssertFatal(1==0,"no long PRACH for this PRACH size %d\n",fp->N_RB_UL); + else { + if (use_extended_prach_prefix) + Ncp+=32; // 16*kappa, kappa=2 for 61.44Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { + idft(IDFT_512,prachF,prach2,1); + // here we have |empty | Prach512 | + if (prach_fmt_id != 9) { + memmove(prach2+(512<<1),prach2,(512<<2)); + prach_len = (512*2)+Ncp; + } + else prach_len = (512*1)+Ncp; + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have |Prefix | Prach512 | Prach512 (if ! 0xc0) | + } else if (prach_fmt_id == 5) { // 6x512 + idft(IDFT_512,prachF,prach2,1); + // here we have |empty | Prach512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have |empty | Prach512 | Prach512| empty512 | empty512 | + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have |Prefix | Prach512 | + prach_len = (512*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x512 + idft(IDFT_512,prachF,prach2,1); + // here we have |empty | Prach512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have |empty | Prach512 | Prach512| empty512 | empty512 | empty512 | empty512 + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | empty512 | empty512 + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have |Prefix | Prach512 | + prach_len = (512*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x512 + idft(IDFT_512,prachF,prach2,1); + // here we have |empty | Prach512 | + memmove(prach2+(512<<1),prach2,(512<<2)); + // here we have |empty | Prach512 | Prach512| empty512 | empty512 | empty512 | empty512 + memmove(prach2+(512<<2),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | empty512 | empty512 + memmove(prach2+(512<<3),prach2,(512<<3)); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 + memmove(prach2+(512<<1)*6,prach2,(512<<2)*6); + // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512| + memmove(prach,prach+(512<<1),(Ncp<<2)); + // here we have |Prefix | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512| + prach_len = (512*12)+Ncp; + } + } + } + else + AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL); + + } + else if (fp->N_RB_UL <= 68) {//66 PRB case, 122.88 Msps + if (fp->threequarter_fs == 0) { + Ncp<<=2; //to account for 122.88Mbps + // This is after cyclic prefix + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_sequence_length == 0) + AssertFatal(1==0,"no long PRACH for this PRACH size %d\n",fp->N_RB_UL); + else { + if (use_extended_prach_prefix) + Ncp+=64; // 16*kappa, kappa=4 for 122.88Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { + idft(IDFT_1024,prachF,prach2,1); + // here we have |empty | Prach1024 | + if (prach_fmt_id != 9) { + memmove(prach2+(1024<<1),prach2,(1024<<2)); + prach_len = (1024*2)+Ncp; + } + else prach_len = (1024*1)+Ncp; + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have |Prefix | Prach1024 | Prach1024 (if ! 0xc0) | + } else if (prach_fmt_id == 5) { // 6x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have |empty | Prach1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have |empty | Prach1024 | Prach1024| empty1024 | empty1024 | + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have |Prefix | Prach1024 | + prach_len = (1024*4)+Ncp; + } else if (prach_fmt_id == 6) { // 6x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have |empty | Prach1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have |empty | Prach1024 | Prach1024| empty1024 | empty1024 | empty1024 | empty1024 + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | empty1024 | empty1024 + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have |Prefix | Prach1024 | + prach_len = (1024*6)+Ncp; + } else if (prach_fmt_id == 8) { // 12x1024 + idft(IDFT_1024,prachF,prach2,1); + // here we have |empty | Prach1024 | + memmove(prach2+(1024<<1),prach2,(1024<<2)); + // here we have |empty | Prach1024 | Prach1024| empty1024 | empty1024 | empty1024 | empty1024 + memmove(prach2+(1024<<2),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | empty1024 | empty1024 + memmove(prach2+(1024<<3),prach2,(1024<<3)); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 + memmove(prach2+(1024<<1)*6,prach2,(1024<<2)*6); + // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024| + memmove(prach,prach+(1024<<1),(Ncp<<2)); + // here we have |Prefix | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024| + prach_len = (1024*12)+Ncp; + } + } + } + else + AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL); + } else if (fp->N_RB_UL < 137) { // 46.08 or 61.44 Ms/s if (fp->threequarter_fs == 0) { // full sampling @ 61.44 Ms/s - Ncp<<=1; - // This is after cyclic prefix (Ncp<<1 samples for 30.72 Ms/s, Ncp<<2 samples for 61.44 Ms/s - prach2 = prach+(Ncp<<1); + Ncp<<=1; //to account for 61.44Mbps + // This is after cyclic prefix + prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { //24576 samples @ 30.72 Ms/s, 49152 samples @ 61.44 Ms/s idft(IDFT_49152,prachF,prach2,1); @@ -442,9 +598,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (12288*4)+Ncp; } } else { // short PRACH sequence + if (use_extended_prach_prefix) + Ncp+=32; // 16*kappa, kappa=2 for 61.44Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { - Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | if (prach_fmt_id != 9) { @@ -455,8 +612,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(2048<<1),(Ncp<<2)); // here we have |Prefix | Prach2048 | Prach2048 (if ! 0xc0) | } else if (prach_fmt_id == 5) { // 6x2048 - Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | memmove(prach2+(2048<<1),prach2,(2048<<2)); @@ -467,8 +622,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach2048 | prach_len = (2048*4)+Ncp; } else if (prach_fmt_id == 6) { // 6x2048 - Ncp+=32; - prach2 = prach+(Ncp<<1); idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | memmove(prach2+(2048<<1),prach2,(2048<<2)); @@ -481,8 +634,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach2048 | prach_len = (2048*6)+Ncp; } else if (prach_fmt_id == 8) { // 12x2048 - Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | memmove(prach2+(2048<<1),prach2,(2048<<2)); @@ -535,9 +686,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (9216*4)+Ncp; } } else { // short sequence + if (use_extended_prach_prefix) + Ncp+=24; // 16*kappa, kappa=1.5 for 46.08Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { - Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | if (prach_fmt_id != 9) { @@ -549,9 +701,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach1536 | Prach1536 (if ! 0xc0) | } else if (prach_fmt_id == 5) { // 6x1536 - - Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | memmove(prach2+(1536<<1),prach2,(1536<<2)); @@ -562,8 +711,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach1536 | prach_len = (1536*4)+Ncp; } else if (prach_fmt_id == 6) { // 6x1536 - Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | memmove(prach2+(1536<<1),prach2,(1536<<2)); @@ -576,8 +723,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach1536 | prach_len = (1536*6)+Ncp; } else if (prach_fmt_id == 8) { // 12x1536 - Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | memmove(prach2+(1536<<1),prach2,(1536<<2)); @@ -596,8 +741,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } } else if (fp->N_RB_UL <= 273) {// 92.16 or 122.88 Ms/s if (fp->threequarter_fs == 0) { // full sampling @ 122.88 Ms/s - Ncp<<=2; - prach2 = prach+(Ncp<<1); + Ncp<<=2; //to account for 122.88Mbps + // This is after cyclic prefix + prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { //24576 samples @ 30.72 Ms/s, 98304 samples @ 122.88 Ms/s idft(IDFT_98304,prachF,prach2,1); @@ -632,9 +778,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (24576*4)+Ncp; } } else { // short sequence + if (use_extended_prach_prefix) + Ncp+=64; // 16*kappa, kappa=4 for 122.88Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { - Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | if (prach_fmt_id != 9) { @@ -644,8 +791,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ memmove(prach,prach+(4096<<1),(Ncp<<2)); // here we have |Prefix | Prach4096 | Prach4096 (if ! 0xc0) | } else if (prach_fmt_id == 5) { // 4x4096 - Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | memmove(prach2+(4096<<1),prach2,(4096<<2)); @@ -656,8 +801,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach4096 | prach_len = (4096*4)+Ncp; } else if (prach_fmt_id == 6) { // 6x4096 - Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | memmove(prach2+(4096<<1),prach2,(4096<<2)); @@ -670,8 +813,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach4096 | prach_len = (4096*6)+Ncp; } else if (prach_fmt_id == 8) { // 12x4096 - Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | memmove(prach2+(4096<<1),prach2,(4096<<2)); @@ -688,8 +829,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } } } else { // three quarter sampling @ 92.16 Ms/s - Ncp = (Ncp*3); - prach2 = prach+(Ncp<<1); + Ncp = (Ncp*3); //to account for 92.16 Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { idft(IDFT_73728,prachF,prach2,1); @@ -724,20 +865,19 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_len = (18432*4)+Ncp; } } else { // short sequence - if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { - Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); + if (use_extended_prach_prefix) + Ncp+=48; // 16*kappa, kappa=3 for 92.16Msps + prach2 = prach+(Ncp<<1); //times 2 for complex samples + if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) { idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | if (prach_fmt_id != 9) { memmove(prach2+(3072<<1),prach2,(3072<<2)); prach_len = (3072*2)+Ncp; } else prach_len = (3072*1)+Ncp; - memmove(prach,prach+(3072<<1),(Ncp<<2)); - // here we have |Prefix | Prach3072 | Prach3072 (if ! 0xc0) | + memmove(prach,prach+(3072<<1),(Ncp<<2)); + // here we have |Prefix | Prach3072 | Prach3072 (if ! 0xc0) | } else if (prach_fmt_id == 6) { // 6x3072 - Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | memmove(prach2+(3072<<1),prach2,(3072<<2)); @@ -750,8 +890,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach3072 | prach_len = (3072*6)+Ncp; } else if (prach_fmt_id == 5) { // 4x3072 - Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | memmove(prach2+(3072<<1),prach2,(3072<<2)); @@ -762,8 +900,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach3072 | prach_len = (3072*4)+Ncp; } else if (prach_fmt_id == 6) { // 12x3072 - Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling - prach2 = prach+(Ncp<<1); idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | memmove(prach2+(3072<<1),prach2,(3072<<2)); 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 86e46402fd..6648197153 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -564,6 +564,18 @@ void nr_dlsch_64qam_llr(NR_DL_FRAME_PARMS *frame_parms, uint32_t llr_offset, uint8_t beamforming_mode); +void nr_dlsch_256qam_llr(NR_DL_FRAME_PARMS *frame_parms, + int32_t **rxdataF_comp, + int16_t *dlsch_llr, + int32_t **dl_ch_mag, + int32_t **dl_ch_magb, + int32_t **dl_ch_magr, + uint8_t symbol, + uint32_t len, + uint8_t first_symbol_flag, + uint16_t nb_rb, + uint32_t llr_offset, + uint8_t beamforming_mode); /** \fn dlsch_siso(NR_DL_FRAME_PARMS *frame_parms, int32_t **rxdataF_comp, @@ -707,7 +719,8 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF, unsigned short nb_pdsch_rb, unsigned char nr_slot_rx, uint32_t high_speed_flag, - NR_DL_FRAME_PARMS *frame_parms); + NR_DL_FRAME_PARMS *frame_parms, + uint16_t dlDmrsSymbPos); /** \fn dlsch_extract_rbs_dual(int32_t **rxdataF, int32_t **dl_ch_estimates, @@ -797,6 +810,7 @@ void nr_dlsch_channel_compensation(int32_t **rxdataF_ext, int32_t **dl_ch_estimates_ext, int32_t **dl_ch_mag, int32_t **dl_ch_magb, + int32_t **dl_ch_magr, int32_t **rxdataF_comp, int32_t **rho, NR_DL_FRAME_PARMS *frame_parms, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index a3e202d4fe..7d0febbb5a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -141,6 +141,8 @@ typedef struct { uint8_t decode_phich; // Encoder BG uint8_t BG; + // LDPC lifting size + uint32_t Z; } NR_UL_UE_HARQ_t; typedef struct { @@ -316,6 +318,19 @@ typedef struct { uint8_t codeword; /// HARQ-ACKs NR_UE_HARQ_STATUS_t harq_ack; + /// PTRS Frequency Density + uint8_t PTRSFreqDensity; + /// PTRS Time Density + uint8_t PTRSTimeDensity; + uint8_t PTRSPortIndex ; + uint8_t nEpreRatioOfPDSCHToPTRS; + uint8_t PTRSReOffset; + /// bit mask of PT-RS ofdm symbol indicies + uint16_t ptrs_symbols; + // PTRS symbol index, to be updated every PTRS symbol within a slot. + uint8_t ptrs_symbol_index; + /// PDU BITMAP + uint16_t pduBitmap; } NR_DL_UE_HARQ_t; typedef struct { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index fdd40feeba..d9bea8a3ac 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -227,8 +227,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, NR_UL_UE_HARQ_t *harq_process; uint16_t nb_rb ; uint32_t A, F; - static uint32_t Z = 0; - uint32_t *pz = &Z; + uint32_t *pz; uint8_t mod_order; uint16_t Kr,r; uint32_t r_offset; @@ -249,7 +248,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, harq_process = ulsch->harq_processes[harq_pid]; nb_rb = harq_process->pusch_pdu.rb_size; A = harq_process->pusch_pdu.pusch_data.tb_size*8; - pz = &Z; + pz = &harq_process->Z; mod_order = nr_get_Qm_ul(harq_process->pusch_pdu.mcs_index, harq_process->pusch_pdu.mcs_table); R = nr_get_code_rate_ul(harq_process->pusch_pdu.mcs_index, harq_process->pusch_pdu.mcs_table); Kr=0; @@ -387,12 +386,13 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, printf("%d \n", harq_process->d[0][cnt]); } printf("\n");*/ - encoder_implemparams_t impp; - impp.n_segments = harq_process->C; - impp.tinput = NULL; - impp.tprep = NULL; - impp.tparity = NULL; - impp.toutput = NULL; + encoder_implemparams_t impp = { + .n_segments=harq_process->C, + .macro_num=0, + .tinput = NULL, + .tprep = NULL, + .tparity = NULL, + .toutput = NULL}; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN); diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 557b8bfc30..f1021ead9b 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -389,6 +389,8 @@ typedef struct { short n0_subband_power_tot_dB[100]; //! estimated avg noise power per RB (dBm) short n0_subband_power_tot_dBm[100]; + //! etimated avg noise power over all RB (dB) + short n0_subband_power_avg_dB; // eNB measurements (per user) //! estimated received spatial signal power (linear) unsigned int rx_spatial_power[NUMBER_OF_UE_MAX][2][2]; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index b6ffd06c2b..cf5f74856e 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -112,6 +112,8 @@ typedef struct { uint32_t F; /// Encoder BG uint8_t BG; + /// LDPC lifting size + uint32_t Z; } NR_DL_gNB_HARQ_t; typedef struct { @@ -467,7 +469,7 @@ typedef struct { /// bit mask of PT-RS ofdm symbol indicies uint16_t ptrs_symbols; // PTRS subcarriers per OFDM symbol - uint16_t ptrs_sc_per_ofdm_symbol; + int32_t ptrs_re_per_slot; /// \brief Estimated phase error based upon PTRS on each symbol . /// - first index: ? [0..7] Number of Antenna /// - second index: ? [0...14] smybol per slot diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 8d31eb15f6..942fd9496a 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -338,6 +338,10 @@ typedef struct { /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_estimates_ext; + /// \brief Downlink channel estimates extracted in PRBS. + /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx + /// - second index: ? [0..168*N_RB_DL[ + int32_t **dl_ch_ptrs_estimates_ext; /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. For the SIC receiver we need to store the history of this for each harq process and round /// - first index: ? [0..7] (hard coded) accessed via \c harq_pid /// - second index: ? [0..7] (hard coded) accessed via \c round @@ -375,6 +379,8 @@ typedef struct { /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx /// - second index: ? [0..168*N_RB_DL[ int32_t **dl_ch_magb1[8][8]; + /// \brief Magnitude of Downlink Channel, first layer (256QAM level). + int32_t **dl_ch_magr0; /// \brief Cross-correlation of two eNB signals. /// - first index: rx antenna [0..nb_antennas_rx[ /// - second index: symbol [0..] @@ -414,6 +420,16 @@ typedef struct { uint32_t llr_offset[14]; // llr length per ofdm symbol uint32_t llr_length[14]; + // llr offset per ofdm symbol + uint32_t dl_valid_re[14]; + /// \brief Estimated phase error based upon PTRS on each symbol . + /// - first index: ? [0..7] Number of Antenna + /// - second index: ? [0...14] smybol per slot + int32_t **ptrs_phase_per_slot; + /// \brief Estimated phase error based upon PTRS on each symbol . + /// - first index: ? [0..7] Number of Antenna + /// - second index: ? [0...14] smybol per slot + int32_t **ptrs_re_per_slot; } NR_UE_PDSCH; #define NR_PDCCH_DEFS_NR_UE @@ -889,7 +905,7 @@ typedef struct { uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD]; /// PDSCH DMRS - uint32_t nr_gold_pdsch[2][20][2][NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD]; + uint32_t nr_gold_pdsch[2][20][14][NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD]; /// PDCCH DMRS uint32_t nr_gold_pdcch[7][20][3][52]; diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index e5678f894d..89c6a2d9c8 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -228,7 +228,7 @@ typedef struct { /// Pointer to Msg3 payload for UL-grant uint8_t *Msg3; /// Frame of last completed synch - uint8_t sync_frame; + uint16_t sync_frame; /// Flag to indicate that prach is ready to start: it is enabled with an initial delay after the sync uint8_t init_msg1; } NR_PRACH_RESOURCES_t; diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index 6c3d97838d..a8548af8dc 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -219,6 +219,13 @@ ///Third Amplitude for QAM64 (\f$ 2^{15} \times 1/\sqrt{42}\f$) #define QAM64_n3 5056 +///First Amplitude for QAM256 (\f$ 2^{15} \times 8/\sqrt{170}\f$) +#define QAM256_n1 20106 +///Second Amplitude for QAM256 (\f$ 2^{15} \times 4/\sqrt{170}\f$) +#define QAM256_n2 10053 +///Third Amplitude for QAM256 (\f$ 2^{15} \times 2/\sqrt{170}\f$) +#define QAM256_n3 5026 + /// First Amplitude for QAM16 for TM5 (\f$ 2^{15} \times 2/sqrt(20)\f$) #define QAM16_TM5_n1 14654 /// Second Amplitude for QAM16 for TM5 Receiver (\f$ 2^{15} \times 1/\sqrt{20}\f$) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 5f0ff6cff0..a37f95bcb3 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -757,8 +757,8 @@ void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int // pdu->rx_ue_information.handle = handle; pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->rx_ue_information.rnti = rnti; - int SNRtimes10 = dB_fixed_times10(stat) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; - LOG_D(PHY,"stat %d subbandpower %d, SNRtimes10 %d\n", stat, eNB->measurements.n0_subband_power_dB[0][0], SNRtimes10); + int SNRtimes10 = dB_fixed_times10(stat) - 10 * eNB->measurements.n0_subband_power_avg_dB; + LOG_D(PHY,"stat %d subband n0 %d, SNRtimes10 %d\n", stat, eNB->measurements.n0_subband_power_avg_dB, SNRtimes10); pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; if (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0; @@ -1604,8 +1604,8 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, timing_advance_update = 63; pdu->rx_indication_rel8.timing_advance = timing_advance_update; - // estimate UL_CQI for MAC (from antenna port 0 only) - int SNRtimes10 = dB_fixed_times10(eNB->pusch_vars[UE_id]->ulsch_power[0]) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; + // estimate UL_CQI for MAC + int SNRtimes10 = dB_fixed_times10(eNB->pusch_vars[UE_id]->ulsch_power[0] + ((eNB->frame_parms.nb_antennas_rx>1) ?eNB->pusch_vars[UE_id]->ulsch_power[1] : 0 )) - 10 * eNB->measurements.n0_subband_power_avg_dB; if (SNRtimes10 < -640) pdu->rx_indication_rel8.ul_cqi = 0; @@ -1614,8 +1614,8 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, else pdu->rx_indication_rel8.ul_cqi = (640 + SNRtimes10) / 5; - LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d), timing_advance %d (update %d)\n", - harq_pid,frame,subframe,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,pdu->rx_indication_rel8.timing_advance, + LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d,%d), timing_advance %d (update %d)\n", + harq_pid,frame,subframe,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,eNB->measurements.n0_subband_power_avg_dB,pdu->rx_indication_rel8.timing_advance, timing_advance_update); eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++; eNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | subframe; @@ -1919,7 +1919,7 @@ void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, in pdu->rx_ue_information.rnti = uci->rnti; // estimate UL_CQI for MAC (from antenna port 0 only) pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; - int SNRtimes10 = dB_fixed_times10(uci->stat) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; + int SNRtimes10 = dB_fixed_times10(uci->stat) - 10 * eNB->measurements.n0_subband_power_avg_dB; if (SNRtimes10 < -100) LOG_I (PHY, "uci->stat %d \n", uci->stat); @@ -2132,17 +2132,17 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { lte_eNB_I0_measurements (eNB, subframe, 0, eNB->first_run_I0_measurements); int min_I0=1000,max_I0=0; - - if ((frame==0) && (subframe==4)) { + int amin=0,amax=0; + if ((frame==0) && (subframe==3)) { for (int i=0; iframe_parms.N_RB_UL; i++) { if (i==(eNB->frame_parms.N_RB_UL>>1) - 1) i+=2; - if (eNB->measurements.n0_subband_power_tot_dB[i]measurements.n0_subband_power_tot_dB[i]; + if (eNB->measurements.n0_subband_power_tot_dB[i]measurements.n0_subband_power_tot_dB[i]; amin=i;} - if (eNB->measurements.n0_subband_power_tot_dB[i]>max_I0) max_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; + if (eNB->measurements.n0_subband_power_tot_dB[i]>max_I0) {max_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; amax=i;} } - LOG_I (PHY, "max_I0 %d, min_I0 %d\n", max_I0, min_I0); + LOG_I (PHY, "max_I0 %d (rb %d), min_I0 %d (rb %d), avg I0 %d\n", max_I0, amax, min_I0, amin, eNB->measurements.n0_subband_power_avg_dB); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 ); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index ff6495c493..6b5c1a9b22 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -239,7 +239,7 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { if (decodeSuccess) { memcpy(ulsch_harq->b+rdata->offset, ulsch_harq->c[r], - rdata->Kr_bytes- - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0)); + rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0)); } else { if ( rdata->nbSegments != ulsch_harq->processedSegments ) { diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 4e6bc7497f..c600343ed0 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -108,9 +108,16 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->harq_ack.pucch_resource_indicator = dlsch_config_pdu->pucch_resource_id; dlsch0_harq->harq_ack.slot_for_feedback_ack = (slot+dlsch_config_pdu->pdsch_to_harq_feedback_time_ind)%frame_parms.slots_per_frame; dlsch0_harq->Nl=1; - dlsch0_harq->mcs_table=0; + dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table; dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); dlsch0_harq->harq_ack.vDAI_DL = dlsch_config_pdu->dai; + /* PTRS */ + dlsch0_harq->PTRSFreqDensity = dlsch_config_pdu->PTRSFreqDensity; + dlsch0_harq->PTRSTimeDensity = dlsch_config_pdu->PTRSTimeDensity; + dlsch0_harq->PTRSPortIndex = dlsch_config_pdu->PTRSPortIndex; + dlsch0_harq->nEpreRatioOfPDSCHToPTRS = dlsch_config_pdu->nEpreRatioOfPDSCHToPTRS; + dlsch0_harq->PTRSReOffset = dlsch_config_pdu->PTRSReOffset; + dlsch0_harq->pduBitmap = dlsch_config_pdu->pduBitmap; LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\n", dlsch0->g_pucch, dlsch0_harq->mcs); } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index d2038cd161..ae85135ba0 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -194,7 +194,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, start_meas(&ue->phy_proc_tx); #endif - if (ue->UE_mode[gNB_id] <= PUSCH || get_softmodem_params()->phy_test == 1){ + if (ue->UE_mode[gNB_id] <= PUSCH){ if (ue->ulsch[proc->thread_id][gNB_id][0]->harq_processes[harq_pid]->status == ACTIVE) nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, proc->thread_id, gNB_id); @@ -311,7 +311,6 @@ void nr_ue_pbch_procedures(uint8_t gNB_id, { // int i; //int pbch_tx_ant=0; - //uint8_t pbch_phase; int ret = 0; //static uint8_t first_run = 1; //uint8_t pbch_trials = 0; @@ -323,7 +322,7 @@ void nr_ue_pbch_procedures(uint8_t gNB_id, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN); - //LOG_I(PHY,"[UE %d] Frame %d, Trying PBCH %d (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,pbch_phase,ue->frame_parms.Nid_cell,gNB_id); + LOG_D(PHY,"[UE %d] Frame %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,ue->frame_parms.Nid_cell,gNB_id); ret = nr_rx_pbch(ue, proc, ue->pbch_vars[gNB_id], @@ -733,8 +732,7 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_ LOG_D(PHY,"[UE %d] PDSCH type %d active in nr_slot_rx %d, harq_pid %d (%d), rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x\n",ue->Mod_id,pdsch,nr_slot_rx,harq_pid,dlsch0->harq_processes[harq_pid]->status,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0->harq_processes[harq_pid]->dlDmrsSymbPos); - // do channel estimation for first DMRS only - for (m = s0; m < 3; m++) { + for (m = s0; m < (s0 +s1); m++) { if (((1<harq_processes[harq_pid]->dlDmrsSymbPos) > 0) { for (uint8_t aatx=0; aatx<1; aatx++) {//for MIMO Config: it shall loop over no_layers nr_pdsch_channel_estimation(ue, @@ -752,12 +750,13 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_ char filename[100]; for (uint8_t aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { sprintf(filename,"PDSCH_CHANNEL_frame%d_slot%d_sym%d_port%d_rx%d.m", nr_frame_rx, nr_slot_rx, m, aatx,aarx); - int **dl_ch_estimates = ue->pdsch_vars[ue->current_thread_id[nr_slot_rx]][0]->dl_ch_estimates; + int **dl_ch_estimates = ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_estimates; LOG_M(filename,"channel_F",&dl_ch_estimates[aatx*ue->frame_parms.nb_antennas_rx+aarx][ue->frame_parms.ofdm_symbol_size*m],ue->frame_parms.ofdm_symbol_size, 1, 1); } #endif } - break; + if ( ue->high_speed_flag == 0 ) //for slow speed case only estimate the channel once per slot + break; } } for (m = s0; m < (s1 + s0); m++) { @@ -930,7 +929,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, uint8_t is_cw0_active = 0; uint8_t is_cw1_active = 0; uint8_t dmrs_type, nb_re_dmrs; - uint16_t length_dmrs = 1; + uint16_t dmrs_len = get_num_dmrs(dlsch0->harq_processes[dlsch0->current_harq_pid]->dlDmrsSymbPos); uint16_t nb_symb_sch = 9; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind; @@ -1016,7 +1015,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, dlsch0->harq_processes[harq_pid]->G = nr_get_G(dlsch0->harq_processes[harq_pid]->nb_rb, nb_symb_sch, nb_re_dmrs, - length_dmrs, + dmrs_len, dlsch0->harq_processes[harq_pid]->Qm, dlsch0->harq_processes[harq_pid]->Nl); #if UE_TIMING_TRACE @@ -1099,11 +1098,11 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, if(is_cw1_active) { // start ldpc decode for CW 1 - dlsch1->harq_processes[harq_pid]->G = nr_get_G(dlsch1->harq_processes[harq_pid]->nb_rb, - nb_symb_sch, - nb_re_dmrs, - length_dmrs, - dlsch1->harq_processes[harq_pid]->Qm, + dlsch1->harq_processes[harq_pid]->G = nr_get_G(dlsch1->harq_processes[harq_pid]->nb_rb, + nb_symb_sch, + nb_re_dmrs, + dmrs_len, + dlsch1->harq_processes[harq_pid]->Qm, dlsch1->harq_processes[harq_pid]->Nl); #if UE_TIMING_TRACE start_meas(&ue->dlsch_unscrambling_stats); @@ -1710,7 +1709,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; int slot_pbch; - //int slot_ssb; + int slot_ssb; NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][0]; fapi_nr_config_request_t *cfg = &ue->nrUE_config; @@ -1734,38 +1733,38 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, if (pdcch_vars->nb_search_space > 0) get_coreset_rballoc(pdcch_vars->pdcch_config[0].coreset.frequency_domain_resource,&coreset_nb_rb,&coreset_start_rb); - + slot_pbch = is_pbch_in_slot(cfg, frame_rx, nr_slot_rx, fp); - //slot_ssb = is_ssb_in_slot(cfg, frame_rx, nr_slot_rx, fp); + slot_ssb = is_ssb_in_slot(cfg, frame_rx, nr_slot_rx, fp); // looking for pbch only in slot where it is supposed to be - if ((ue->decode_MIB == 1) && slot_pbch) - { - LOG_D(PHY," ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); - for (int i=1; i<4; i++) { + if (slot_ssb) { + LOG_D(PHY," ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); + for (int i=1; i<4; i++) { - nr_slot_fep(ue, - proc, - (ue->symbol_offset+i)%(fp->symbols_per_slot), - nr_slot_rx, - 0, - 0); + nr_slot_fep(ue, + proc, + (ue->symbol_offset+i)%(fp->symbols_per_slot), + nr_slot_rx, + 0, + 0); #if UE_TIMING_TRACE - start_meas(&ue->dlsch_channel_estimation_stats); + start_meas(&ue->dlsch_channel_estimation_stats); #endif - nr_pbch_channel_estimation(ue,proc,0,nr_slot_rx,(ue->symbol_offset+i)%(fp->symbols_per_slot),i-1,(fp->ssb_index)&7,fp->half_frame_bit); + nr_pbch_channel_estimation(ue,proc,0,nr_slot_rx,(ue->symbol_offset+i)%(fp->symbols_per_slot),i-1,(fp->ssb_index)&7,fp->half_frame_bit); #if UE_TIMING_TRACE - stop_meas(&ue->dlsch_channel_estimation_stats); + stop_meas(&ue->dlsch_channel_estimation_stats); #endif + } - } - - //if (mac->csirc->reportQuantity.choice.ssb_Index_RSRP){ - nr_ue_rsrp_measurements(ue, proc, nr_slot_rx, 0); - //} - + //if (mac->csirc->reportQuantity.choice.ssb_Index_RSRP){ + nr_ue_rsrp_measurements(ue,proc,nr_slot_rx,0); + //} + if ((ue->decode_MIB == 1) && slot_pbch) { + + LOG_D(PHY," ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); nr_ue_pbch_procedures(gNB_id, ue, proc, 0); if (ue->no_timing_correction==0) { @@ -1779,6 +1778,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, 16384); } } + } if ((frame_rx%64 == 0) && (nr_slot_rx==0)) { printf("============================================\n"); @@ -1851,7 +1851,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, for (int i=0;i<4;i++) if (((1<dlDmrsSymbPos) > 0) {symb_dmrs=i;break;} AssertFatal(symb_dmrs>=0,"no dmrs in 0..3\n"); LOG_D(PHY,"Initializing dmrs for symb %d DMRS mask %x\n",symb_dmrs,dlsch0_harq->dlDmrsSymbPos); - nr_gold_pdsch(ue,symb_dmrs,0, 1); + nr_gold_pdsch(ue,0); for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ nr_slot_fep(ue, @@ -2019,7 +2019,7 @@ start_meas(&ue->generic_stat); if(nr_slot_rx==5 && ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid]->nb_rb > 20){ //write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); - //write_output("llr.m","llr", &ue->pdsch_vars[gNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); + //write_output("llr.m","llr", &ue->pdsch_vars[proc->thread_id][gNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0); write_output("rxdataF0_current.m" , "rxdataF0", &ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1); //write_output("rxdataF0_previous.m" , "rxdataF0_prev_sss", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1); @@ -2027,10 +2027,10 @@ start_meas(&ue->generic_stat); //write_output("rxdataF0_previous.m" , "rxdataF0_prev", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1); write_output("dl_ch_estimates.m", "dl_ch_estimates_sfn5", &ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].dl_ch_estimates[0][0][0],14*fp->ofdm_symbol_size,1,1); - write_output("dl_ch_estimates_ext.m", "dl_ch_estimatesExt_sfn5", &ue->pdsch_vars[proc->thread_id][0]->dl_ch_estimates_ext[0][0],14*fp->N_RB_DL*12,1,1); - write_output("rxdataF_comp00.m","rxdataF_comp00", &ue->pdsch_vars[proc->thread_id][0]->rxdataF_comp0[0][0],14*fp->N_RB_DL*12,1,1); - //write_output("magDLFirst.m", "magDLFirst", &phy_vars_ue->pdsch_vars[proc->thread_id][0]->dl_ch_mag0[0][0],14*fp->N_RB_DL*12,1,1); - //write_output("magDLSecond.m", "magDLSecond", &phy_vars_ue->pdsch_vars[proc->thread_id][0]->dl_ch_magb0[0][0],14*fp->N_RB_DL*12,1,1); + write_output("dl_ch_estimates_ext.m", "dl_ch_estimatesExt_sfn5", &ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates_ext[0][0],14*fp->N_RB_DL*12,1,1); + write_output("rxdataF_comp00.m","rxdataF_comp00", &ue->pdsch_vars[proc->thread_id][gNB_id]->rxdataF_comp0[0][0],14*fp->N_RB_DL*12,1,1); + //write_output("magDLFirst.m", "magDLFirst", &phy_vars_ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_mag0[0][0],14*fp->N_RB_DL*12,1,1); + //write_output("magDLSecond.m", "magDLSecond", &phy_vars_ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_magb0[0][0],14*fp->N_RB_DL*12,1,1); AssertFatal (0,""); } @@ -2165,7 +2165,7 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN); - if (!prach_resources->init_msg1 && (frame_tx == (ue->prach_resources[gNB_id]->sync_frame + 150) % MAX_FRAME_NUMBER)){ + if (!prach_resources->init_msg1 && ((MAX_FRAME_NUMBER+frame_tx-ue->prach_resources[gNB_id]->sync_frame)% MAX_FRAME_NUMBER)>150){ ue->prach_cnt = 0; prach_resources->init_msg1 = 1; } diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index 9a19aef985..1e5a51450d 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -33,6 +33,7 @@ * **************************************************************************/ +#include "executables/softmodem-common.h" #include "PHY/NR_REFSIG/ss_pbch_nr.h" #include "PHY/defs_nr_UE.h" #include @@ -228,13 +229,11 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ int pucch_resource_indicator = MAX_PUCCH_RESOURCE_INDICATOR; int n_HARQ_ACK; - uint16_t crnti=0x1234; int dmrs_scrambling_id=0,data_scrambling_id=0; - NR_UE_MAC_INST_t *mac = get_mac_inst(0); NR_PUCCH_Resource_t *pucch_resource; - //NR_UE_MAC_INST_t *mac = get_mac_inst(0); + uint16_t crnti = mac->crnti; /* update current context */ @@ -1008,6 +1007,12 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8 if (resource_set_found == TRUE) { if (pucch_resource_indicator < MAX_PUCCH_RESOURCE_INDICATOR) { + // Verify that the value of pucch_resource_indicator is valid + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.count <= pucch_resource_indicator) + { + LOG_E(PHY, "Value of pucch_resource_indicator is out of bounds! Possibly due to a false DCI. \n"); + return (FALSE); + } /* check if resource indexing by pucch_resource_indicator of this set is compatible */ if ((ready_pucch_resource_id == TRUE) || (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.array[pucch_resource_indicator][0] != MAX_NB_OF_PUCCH_RESOURCES)) { diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 12aace577c..d3f55785c9 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -487,7 +487,7 @@ int n_ch_rlz = 1; int rx_sample_offset = 0; int xforms=0; int dump_table=0; -int loglvl=OAILOG_WARNING; +int loglvl=OAILOG_INFO; int mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0; int two_thread_flag=0; int num_rounds = 4;//,fix_rounds=0; @@ -670,7 +670,7 @@ int main(int argc, char **argv) { { "XForms", "Display the soft scope", PARAMFLAG_BOOL, iptr:&xforms, defintval:0, TYPE_INT, 0 }, { "Yperfect_ce","Perfect CE", PARAMFLAG_BOOL, iptr:&perfect_ce, defintval:0, TYPE_INT, 0 }, { "Zdump", "dump table",PARAMFLAG_BOOL, iptr:&dump_table, defintval:0, TYPE_INT, 0 }, - { "Loglvl", "log level",0, iptr:&loglvl, defintval:OAILOG_DEBUG, TYPE_INT, 0 }, + { "Loglvl", "log level",0, iptr:&loglvl, defintval:OAILOG_INFO, TYPE_INT, 0 }, { "zn_rx", "Number of RX antennas used in UE",0, iptr:NULL, defintval:2, TYPE_INT, 0 }, { "gchannel", "[A:M] Use 3GPP 25.814 SCM-A/B/C/D('A','B','C','D') or 36-101 EPA('E'), EVA ('F'),ETU('G') models (ignores delay spread and Ricean factor), Rayghleigh8 ('H'), Rayleigh1('I'), Rayleigh1_corr('J'), Rayleigh1_anticorr ('K'), Rice8('L'), Rice1('M')",0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0 }, { "verbose", "display debug text", PARAMFLAG_BOOL, iptr:&verbose, defintval:0, TYPE_INT, 0 }, diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 2ca8dae279..70c72edf40 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -61,7 +61,7 @@ #include "openair1/SIMULATION/TOOLS/sim.h" #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h" //#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c" - +#include "PHY/NR_REFSIG/ptrs_nr.h" #include "NR_RRCReconfiguration.h" #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) #include "SIMULATION/LTE_PHY/common_sim.h" @@ -125,6 +125,32 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( return 0; } +int +gtpv1u_create_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, + gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ + return 0; +} + +int +gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +){ + return 0; +} + +int +nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +){ + return 0; +} + void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigCommon_t *scc @@ -148,11 +174,12 @@ int is_x2ap_enabled(void) // needed for some functions openair0_config_t openair0_cfg[MAX_CARDS]; - +void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg); +void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dmrs_arg); /* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs from command line of dlsim, does not search for CCE/PUCCH occasion but simply sets to 0 */ -int g_mcsIndex = -1, g_rbStart = -1, g_rbSize = -1; +int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1; void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot, @@ -180,10 +207,11 @@ void nr_dlsim_preprocessor(module_id_t module_id, sched_ctrl->rbSize = g_rbSize; sched_ctrl->mcs = g_mcsIndex; sched_ctrl->time_domain_allocation = 2; - sched_ctrl->mcsTableIdx = 0; + sched_ctrl->mcsTableIdx = g_mcsTableIdx; AssertFatal(sched_ctrl->rbStart >= 0, "invalid rbStart %d\n", sched_ctrl->rbStart); AssertFatal(sched_ctrl->rbSize > 0, "invalid rbSize %d\n", sched_ctrl->rbSize); AssertFatal(sched_ctrl->mcs >= 0, "invalid sched_ctrl->mcs %d\n", sched_ctrl->mcs); + AssertFatal(sched_ctrl->mcsTableIdx >= 0 && sched_ctrl->mcsTableIdx <= 2, "invalid sched_ctrl->mcsTableIdx %d\n", sched_ctrl->mcsTableIdx); sched_ctrl->numDmrsCdmGrpsNoData = 1; } @@ -255,6 +283,19 @@ int main(int argc, char **argv) int css_flag=0; cpuf = get_cpu_freq_GHz(); + int8_t enable_ptrs = 0; + int8_t modify_dmrs = 0; + + int8_t dmrs_arg[2] = {-1,-1};// Invalid values + /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */ + int8_t ptrs_arg[2] = {-1,-1};// Invalid values + + uint16_t ptrsRePerSymb = 0; + uint16_t pdu_bit_map = 0x0; + uint16_t dlPtrsSymPos = 0; + uint16_t ptrsSymbPerSlot = 0; + uint16_t rbSize = 106; + uint8_t mcsIndex = 9; if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) { exit_fun("[NR_DLSIM] Error, configuration module init failed\n"); @@ -266,7 +307,7 @@ int main(int argc, char **argv) FILE *scg_fd=NULL; - while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:e:m:w")) != -1) { + while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:e:m:w:T:U:q")) != -1) { switch (c) { case 'f': scg_fd = fopen(optarg,"r"); @@ -438,6 +479,11 @@ int main(int argc, char **argv) g_mcsIndex = atoi(optarg); break; + case 'q': + g_mcsTableIdx = 1; + get_softmodem_params()->use_256qam_table = 1; + break; + case 'm': mu = atoi(optarg); break; @@ -450,6 +496,20 @@ int main(int argc, char **argv) output_fd = fopen("txdata.dat", "w+"); break; + case 'T': + enable_ptrs=1; + for(i=0; i < atoi(optarg); i++) { + ptrs_arg[i] = atoi(argv[optind++]); + } + break; + + case 'U': + modify_dmrs = 1; + for(i=0; i < atoi(optarg); i++) { + dmrs_arg[i] = atoi(argv[optind++]); + } + break; + default: case 'h': printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", @@ -479,7 +539,10 @@ int main(int argc, char **argv) printf("-c Start symbol for PDSCH (fixed for now)\n"); printf("-j Number of symbols for PDSCH (fixed for now)\n"); printf("-e MSC index\n"); + printf("-q Use 2nd MCS table (256 QAM table) for PDSCH\n"); printf("-t Acceptable effective throughput (in percentage)\n"); + printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n"); + printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:2}, e.g. -U 2 0 2 \n"); printf("-P Print DLSCH performances\n"); printf("-w Write txdata to binary file (one frame)\n"); exit (-1); @@ -490,6 +553,8 @@ int main(int argc, char **argv) logInit(); set_glog(loglvl); T_stdout = 1; + /* initialize the sin table */ + InitSinLUT(); get_softmodem_params()->phy_test = 1; @@ -578,7 +643,17 @@ int main(int argc, char **argv) n_tx, 0); - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); + /* -U option modify DMRS */ + if(modify_dmrs) { + update_dmrs_config(secondaryCellGroup, NULL,dmrs_arg); + } + /* -T option enable PTRS */ + if(enable_ptrs) { + update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, ptrs_arg); + } + + + //xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface"); gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; @@ -693,6 +768,9 @@ int main(int argc, char **argv) exit(-1); } + if(modify_dmrs) { + update_dmrs_config( NULL,UE,dmrs_arg); + } init_nr_ue_transport(UE,0); nr_gold_pbch(UE); @@ -815,7 +893,6 @@ int main(int argc, char **argv) UE_info->UE_sched_ctrl[0].harq_processes[harq_pid].round = round; - UE_info->UE_sched_ctrl[0].current_harq_pid = harq_pid; gNB->dlsch[0][0]->harq_processes[harq_pid]->round = round; for (int i=0; iUE_info.num_pdcch_cand[0][i] = 0; @@ -833,11 +910,26 @@ int main(int argc, char **argv) Sched_INFO.frame = frame; Sched_INFO.slot = slot; Sched_INFO.DL_req = &gNB_mac->DL_req[0]; - Sched_INFO.UL_tti_req = &gNB_mac->UL_tti_req[0]; + Sched_INFO.UL_tti_req = gNB_mac->UL_tti_req_ahead[slot]; Sched_INFO.UL_dci_req = NULL; Sched_INFO.TX_req = &gNB_mac->TX_req[0]; nr_schedule_response(&Sched_INFO); - + + /* PTRS values for DLSIM calculations */ + nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[Sched_INFO.CC_id].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; + if(pdu_bit_map & 0x1) { + set_ptrs_symb_idx(&dlPtrsSymPos, + pdsch_pdu_rel15->NrOfSymbols, + pdsch_pdu_rel15->StartSymbolIndex, + 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); + printf("[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb ); + } if (run_initial_sync) nr_common_signal_procedures(gNB,frame,slot); else @@ -894,7 +986,7 @@ int main(int argc, char **argv) r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); } } - + double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); //AWGN sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR; sigma2 = pow(10, sigma2_dB/10); @@ -907,6 +999,11 @@ int main(int argc, char **argv) for (aa=0; aanb_antennas_rx; aa++) { ((short*) UE->common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); ((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + /* Add phase noise if enabled */ + if (pdu_bit_map & 0x1) { + phase_noise(ts, &((short*) UE->common_vars.rxdata[aa])[2*i], + &((short*) UE->common_vars.rxdata[aa])[2*i+1]); + } } } @@ -934,13 +1031,17 @@ int main(int argc, char **argv) int16_t *UE_llr = pdsch_vars[0]->llr[0]; TBS = UE_harq_process->TBS;//rel15->TBSize[0]; - uint16_t length_dmrs = 1; + uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos); uint16_t nb_rb = rel15->rbSize; uint8_t nb_re_dmrs = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4; uint8_t mod_order = rel15->qamModOrder[0]; uint8_t nb_symb_sch = rel15->NrOfSymbols; available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers); + if(pdu_bit_map & 0x1) { + available_bits-= (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2); + printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) ); + } for (i = 0; i < available_bits; i++) { @@ -992,7 +1093,7 @@ int main(int argc, char **argv) printf("*****************************************\n"); printf("\n"); dump_pdsch_stats(gNB); - printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %d bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS); + printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS); printf("\n"); if (print_perf==1) { @@ -1102,3 +1203,79 @@ int main(int argc, char **argv) return(n_errors); } + + +void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, int8_t *ptrs_arg) +{ + NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0]; + int *ptrsFreqDenst = calloc(2, sizeof(long)); + ptrsFreqDenst[0]= 25; + ptrsFreqDenst[1]= 115; + int *ptrsTimeDenst = calloc(3, sizeof(long)); + ptrsTimeDenst[0]= 2; + ptrsTimeDenst[1]= 4; + ptrsTimeDenst[2]= 10; + + int epre_Ratio = 0; + int reOffset = 0; + + if(ptrs_arg[0] ==0) { + ptrsTimeDenst[2]= *mcsIndex -1; + } + else if(ptrs_arg[0] == 1) { + ptrsTimeDenst[1]= *mcsIndex - 1; + ptrsTimeDenst[2]= *mcsIndex + 1; + } + else if(ptrs_arg[0] ==2) { + ptrsTimeDenst[0]= *mcsIndex - 1; + ptrsTimeDenst[1]= *mcsIndex + 1; + } + else { + printf("[DLSIM] Wrong L_PTRS value, using default values 1\n"); + } + /* L = 4 if Imcs < MCS4 */ + if(ptrs_arg[1] ==2) { + ptrsFreqDenst[0]= *rbSize - 1; + ptrsFreqDenst[1]= *rbSize + 1; + } + else if(ptrs_arg[1] == 4) { + ptrsFreqDenst[1]= *rbSize - 1; + } + else { + printf("[DLSIM] Wrong K_PTRS value, using default values 2\n"); + } + printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<= 0 && dmrs_arg[1] <3 ) { + add_pos = dmrs_arg[1]; + } + + if(scg != NULL) { + NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0]; + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = add_pos; + for (int i=0;ibwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) { + bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type; + } + } + if(ue != NULL) { + for (int i=0;iPDSCH_Config.pdsch_TimeDomainResourceAllocation[i]->mappingType = mapping_type; + } + ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition = add_pos; + } + printf("[DLSIM] DMRS Config is modified with Mapping Type %d, Additional Positions %d \n", dmrs_arg[0], dmrs_arg[1] ); +} diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 0cc7e9f08a..89d36a0ad2 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -99,6 +99,32 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( return 0; } +int +gtpv1u_create_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, + gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ + return 0; +} + +int +gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +){ + return 0; +} + +int +nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +){ + return 0; +} + int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, const int8_t channel, const uint8_t* pduP, const sdu_size_t pdu_len) {return 0;} // Dummy function to avoid linking error at compilation of nr-prachsim @@ -116,10 +142,10 @@ int main(int argc, char **argv){ int i, aa, aarx, **txdata, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1; 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; 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 frame = 1, subframe = 9, slot=19, slot_gNB=19, config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol; + uint8_t frame = 1, slot=19, slot_gNB=19, config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol; uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1; uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB; - uint64_t SSB_positions = 0x01, absoluteFrequencyPointA = 640000; + uint64_t SSB_positions = 0x01; uint16_t RA_sfn_index; uint8_t N_RA_slot; uint8_t config_period; @@ -153,7 +179,7 @@ int main(int argc, char **argv){ randominit(0); - while ((c = getopt (argc, argv, "hHaA:Cc:r:p:g:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) { + while ((c = getopt (argc, argv, "hHaA:Cc:r:p:g:m:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) { switch (c) { case 'a': printf("Running AWGN simulation\n"); @@ -243,6 +269,10 @@ int main(int argc, char **argv){ threequarter_fs=1; break; + case 'm': + mu = atoi(optarg); + break; + case 'n': n_frames = atoi(optarg); break; @@ -370,13 +400,6 @@ int main(int argc, char **argv){ } } - - if (config_index<67) { prach_sequence_length=0; slot = subframe*2; slot_gNB = 1+(subframe*2); } - uint16_t N_ZC; - N_ZC = prach_sequence_length == 0 ? 839 : 139; - - printf("Config_index %d, prach_sequence_length %d\n",config_index,prach_sequence_length); - // Configure log logInit(); set_glog(loglvl); @@ -411,12 +434,20 @@ int main(int argc, char **argv){ frame_parms->N_RB_UL = N_RB_UL; frame_parms->threequarter_fs = threequarter_fs; frame_parms->frame_type = TDD; - frame_parms->freq_range = nr_FR1; + frame_parms->freq_range = (mu==1 ? nr_FR1 : nr_FR2); frame_parms->numerology_index = mu; nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions); - //nsymb = (frame_parms->Ncp == 0) ? 14 : 12; + uint64_t absoluteFrequencyPointA = (mu==1 ? 640000 : 2070833); + + uint8_t subframe = slot/frame_parms->slots_per_subframe; + + if (config_index<67 && mu==1) { prach_sequence_length=0; slot = subframe*2; slot_gNB = 1+(subframe*2); } + uint16_t N_ZC = prach_sequence_length == 0 ? 839 : 139; + + printf("Config_index %d, prach_sequence_length %d\n",config_index,prach_sequence_length); + printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Frame type %s, Frequency Range %s\n", NUMBER_OF_OFDM_CARRIERS, @@ -432,7 +463,14 @@ int main(int argc, char **argv){ gNB->gNB_config.carrier_config.num_tx_ant.value = 1; gNB->gNB_config.carrier_config.num_rx_ant.value = 1; - gNB->gNB_config.tdd_table.tdd_period.value = 6; + if (mu==1) + gNB->gNB_config.tdd_table.tdd_period.value = 6; + else if (mu==3) + gNB->gNB_config.tdd_table.tdd_period.value = 3; + else { + printf("unsupported numerology %d\n",mu); + exit(-1); + } gNB->gNB_config.prach_config.num_prach_fd_occasions.value = num_prach_fd_occasions; gNB->gNB_config.prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(num_prach_fd_occasions*sizeof(nfapi_nr_num_prach_fd_occasions_t)); @@ -752,7 +790,7 @@ int main(int argc, char **argv){ LOG_M("prachF0.m","prachF0", &gNB->prach_vars.prachF[0], N_ZC, 1, 1); LOG_M("rxsig0.m","rxs0", &gNB->common_vars.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("rxsigF0.m","rxsF0", gNB->prach_vars.rxsigF[0], N_ZC, 1, 1); + LOG_M("ru_rxsigF0.m","rxsF0", ru->prach_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 diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index f2662d9fe6..afebe4ed97 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -81,7 +81,7 @@ int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { if (decodeSuccess) { memcpy(ulsch_harq->b+rdata->offset, ulsch_harq->c[r], - rdata->Kr_bytes- - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0)); + rdata->Kr_bytes - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0)); } else { if ( rdata->nbSegments != ulsch_harq->processedSegments ) { int nb=abortTpool(gNB->threadPool, req->key); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 19b107a80a..7942f7fc7a 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -56,7 +56,7 @@ #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "common/utils/threadPool/thread-pool.h" - +#include "PHY/NR_REFSIG/ptrs_nr.h" #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) #include "SIMULATION/LTE_PHY/common_sim.h" @@ -120,6 +120,32 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( return 0; } +int +gtpv1u_create_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, + gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ + return 0; +} + +int +gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +){ + return 0; +} + +int +nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( + const protocol_ctxt_t *const ctxt_pP, + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, + uint8_t *inde_list +){ + return 0; +} + // Dummy function to avoid linking error at compilation of nr-ulsim int is_x2ap_enabled(void) { @@ -163,8 +189,7 @@ int main(int argc, char **argv) FILE *input_fd = NULL; SCM_t channel_model = AWGN; //Rayleigh1_anticorr; uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1; - double tx_gain=1.0; - double N0=30; + NB_UE_INST = 1; //unsigned char frame_type = 0; @@ -179,7 +204,6 @@ int main(int argc, char **argv) int gNB_id = 0; int ap; int tx_offset; - double txlev_float; int32_t txlev; int start_rb = 0; int UE_id =0; // [hna] only works for UE_id = 0 because NUMBER_OF_NR_UE_MAX is set to 1 (phy_init_nr_gNB causes segmentation fault) @@ -199,6 +223,9 @@ int main(int argc, char **argv) int ptrs_arg[2] = {-1,-1};// Invalid values /* DMRS TYPE = dmrs_arg[0], Add Pos = dmrs_arg[1] */ int dmrs_arg[2] = {-1,-1};// Invalid values + uint16_t ptrsSymPos = 0; + uint16_t ptrsSymbPerSlot = 0; + uint16_t ptrsRePerSymb = 0; UE_nr_rxtx_proc_t UE_proc; FILE *scg_fd=NULL; @@ -217,6 +244,9 @@ int main(int argc, char **argv) //logInit(); randominit(0); + /* initialize the sin-cos table */ + InitSinLUT(); + while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:i:j:kl:m:n:p:r:s:y:z:F:G:H:M:N:PR:S:T:U:L:")) != -1) { printf("handling optarg %c\n",c); switch (c) { @@ -950,8 +980,6 @@ int main(int argc, char **argv) nr_fill_ulsch(gNB,frame,slot,pusch_pdu); for (int i=0;i<(TBS/8);i++) ulsch_ue[0]->harq_processes[harq_pid]->a[i]=i&0xff; - double scale = 1; - if (input_fd == NULL) { // set FAPI parameters for UE, put them in the scheduled response and call @@ -974,20 +1002,16 @@ int main(int argc, char **argv) txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); - - txlev_float = (double)txlev/scale; // output of signal_energy is fixed point representation - - } else n_trials = 1; if (input_fd == NULL ) { - sigma_dB = N0; + sigma_dB = 10 * log10((double)txlev * ((double)frame_parms->ofdm_symbol_size/(12*nb_rb))) - SNR;; sigma = pow(10,sigma_dB/10); - tx_gain = sqrt(pow(10.0,.1*(N0+SNR))/txlev_float); - if(n_trials==1) printf("txlev_float %f, sigma_dB %f, tx_gain %f tx_offset %d, slot_offset %d\n",10*log10(txlev_float),sigma_dB,tx_gain,tx_offset,slot_offset); + + if(n_trials==1) printf("sigma %f (%f dB), txlev %f (factor %f)\n",sigma,sigma_dB,10*log10((double)txlev),(double)(double)frame_parms->ofdm_symbol_size/(12*nb_rb)); for (i=0; inb_antennas_rx; ap++) { - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((tx_gain*r_re[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point - ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((tx_gain*r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)] = (int16_t)((r_re[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point + ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)] = (int16_t)((r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); /* Add phase noise if enabled */ if (pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { phase_noise(ts, &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)], @@ -1018,6 +1042,17 @@ int main(int argc, char **argv) } + + if(pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) { + set_ptrs_symb_idx(&ptrsSymPos, + pusch_pdu->nr_of_symbols, + pusch_pdu->start_symbol_index, + 1<ul_dmrs_symb_pos); + ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymPos, pusch_pdu->start_symbol_index, pusch_pdu->nr_of_symbols); + ptrsRePerSymb = ((pusch_pdu->rb_size + ptrs_freq_density - 1)/ptrs_freq_density); + printf("[ULSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb ); + } //////////////////////////////////////////////////////////// //---------------------------------------------------------- @@ -1082,7 +1117,7 @@ int main(int argc, char **argv) } /* 2*5*(50/2), for RB = 50,K = 2 for 5 OFDM PTRS symbols */ available_bits -= 2 * ptrs_symbols * ((nb_rb + ptrs_freq_density - 1) /ptrs_freq_density); - printf("After PTRS subtraction available_bits are : %u \n", available_bits); + printf("[ULSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5d \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * 2) ); } for (i = 0; i < available_bits; i++) { diff --git a/openair1/SIMULATION/TOOLS/phase_noise.c b/openair1/SIMULATION/TOOLS/phase_noise.c index f243a09c59..5958a0ccdd 100644 --- a/openair1/SIMULATION/TOOLS/phase_noise.c +++ b/openair1/SIMULATION/TOOLS/phase_noise.c @@ -29,14 +29,43 @@ /* linear phase noise model */ void phase_noise(double ts, int16_t * InRe, int16_t * InIm) { + static uint64_t i=0; + int32_t x=0 ,y=0; double fd = 300;//0.01*30000 - static double i=0; - double real, imag,x ,y; + int16_t SinValue = 0, CosValue= 0; + double IdxDouble = (double)(i*fd * ts * ResolSinCos * 4); + int16_t IdxModulo = ((int32_t)(IdxDouble>0 ? IdxDouble+0.5 : IdxDouble-0.5)) % (ResolSinCos*4); + IdxModulo = IdxModulo<0 ? IdxModulo+ResolSinCos*4 : IdxModulo; + + if(IdxModulo<2*ResolSinCos) {//< 2 check for 1st and 2nd + if(IdxModulo < ResolSinCos) {// 1st Quadrant + SinValue = LUTSin[IdxModulo]; + CosValue = LUTSin[ResolSinCos-IdxModulo]; + } + else {// 2nd Quadrant + SinValue = LUTSin[2*ResolSinCos-IdxModulo]; + CosValue = -LUTSin[IdxModulo-ResolSinCos]; + } + } + else {// 3rd and 4th Quadrant + if(IdxModulo < 3*ResolSinCos) {// 3rd Quadrant + SinValue = -LUTSin[IdxModulo-2*ResolSinCos]; + CosValue = -LUTSin[3*ResolSinCos-IdxModulo]; + } + else {//4th Quadrant + SinValue = -LUTSin[4*ResolSinCos-IdxModulo]; + CosValue = LUTSin[IdxModulo-3*ResolSinCos]; + } + } + x = ( ((int32_t)InRe[0] * CosValue) - ((int32_t)InIm[0] * SinValue )); + y = ( ((int32_t)InIm[0] * CosValue) + ((int32_t)InRe[0] * SinValue )); + InRe[0]= (int16_t)(x>>14); + InIm[0]= (int16_t)(y>>14); i++; - real = cos(fd * 2 * M_PI * i * ts); - imag = sin (fd * 2 * M_PI * i * ts); - x = ((real * (double)InRe[0]) - (imag * (double)InIm[0])) ; - y= ((real * (double)InIm[0]) + (imag * (double)InRe[0])) ; - InRe[0]= (int16_t)(x); - InIm[0]= (int16_t)(y); +} +/* Initialisation function for SIN table values */ +void InitSinLUT( void ) { + for ( int i=0; i<(ResolSinCos+1); i++ ) { + LUTSin[i] = sin((double)(M_PI*i)/(2*ResolSinCos)) * (1<<14); //Format: Q14 + } } diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index d2684b15c1..55a78e9778 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -466,6 +466,10 @@ double N_RB2channel_bandwidth(uint16_t N_RB); \param ts Sampling time \param *Re *Im Real and Imag part of the signal */ +//look-up table for the sine (cosine) function +#define ResolSinCos 100 +uint16_t LUTSin[ResolSinCos+1]; +void InitSinLUT( void ); void phase_noise(double ts, int16_t * InRe, int16_t * InIm); #include "targets/RT/USER/rfsim.h" diff --git a/openair2/COMMON/gtpv1_u_messages_def.h b/openair2/COMMON/gtpv1_u_messages_def.h index 8531ce16a0..86103dd911 100644 --- a/openair2/COMMON/gtpv1_u_messages_def.h +++ b/openair2/COMMON/gtpv1_u_messages_def.h @@ -30,4 +30,7 @@ MESSAGE_DEF(GTPV1U_ENB_DATA_FORWARDING_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_dat MESSAGE_DEF(GTPV1U_ENB_END_MARKER_REQ, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_req_t, Gtpv1uEndMarkerReq) MESSAGE_DEF(GTPV1U_ENB_END_MARKER_IND, MESSAGE_PRIORITY_MED, gtpv1u_enb_end_marker_ind_t, Gtpv1uEndMarkerInd) MESSAGE_DEF(GTPV1U_ENB_S1_REQ, MESSAGE_PRIORITY_MED, Gtpv1uS1Req, gtpv1uS1Req) + +MESSAGE_DEF(GTPV1U_GNB_DELETE_TUNNEL_REQ, MESSAGE_PRIORITY_MED, gtpv1u_gnb_delete_tunnel_req_t, NRGtpv1uDeleteTunnelReq) +MESSAGE_DEF(GTPV1U_GNB_DELETE_TUNNEL_RESP, MESSAGE_PRIORITY_MED, gtpv1u_gnb_delete_tunnel_resp_t, NRGtpv1uDeleteTunnelResp) MESSAGE_DEF(GTPV1U_GNB_NG_REQ, MESSAGE_PRIORITY_MED, Gtpv1uNGReq, gtpv1uNGReq) diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index c7e247f0fa..8fde343000 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -40,7 +40,10 @@ #define GTPV1U_ENB_END_MARKER_IND(mSGpTR) (mSGpTR)->ittiMsg.Gtpv1uEndMarkerInd #define GTPV1U_ENB_S1_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uS1Req -#define GTPV1U_GNB_NG_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uNGReq + +#define GTPV1U_GNB_DELETE_TUNNEL_REQ(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uDeleteTunnelReq +#define GTPV1U_GNB_DELETE_TUNNEL_RESP(mSGpTR) (mSGpTR)->ittiMsg.NRGtpv1uDeleteTunnelResp +#define GTPV1U_GNB_NG_REQ(mSGpTR) (mSGpTR)->ittiMsg.gtpv1uNGReq #define GTPV1U_ALL_TUNNELS_TEID (teid_t)0xFFFFFFFF @@ -195,4 +198,16 @@ typedef struct gtpv1u_gnb_create_tunnel_resp_s { transport_layer_addr_t gnb_addr; } gtpv1u_gnb_create_tunnel_resp_t; +typedef struct gtpv1u_gnb_delete_tunnel_req_s { + rnti_t rnti; + uint8_t num_pdusession; + pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; +} gtpv1u_gnb_delete_tunnel_req_t; + +typedef struct gtpv1u_gnb_delete_tunnel_resp_s { + rnti_t rnti; + uint8_t status; ///< Status of NGU endpoint deleteion (Failed = 0xFF or Success = 0x0) + teid_t gnb_NGu_teid; ///< local NGU Tunnel Endpoint Identifier to be deleted +} gtpv1u_gnb_delete_tunnel_resp_t; + #endif /* GTPV1_U_MESSAGES_TYPES_H_ */ diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index a2b40815d6..af746b9193 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -741,6 +741,10 @@ typedef struct ngap_ue_release_command_s { typedef struct pdusession_release_s { /* Unique pdusession_id for the UE. */ uint8_t pdusession_id; + /* Octet string data */ + uint8_t *transfer_buffer; + /* Length of the octet string */ + uint32_t transfer_length; } pdusession_release_t; typedef struct ngap_ue_release_req_s { diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index 08ecde26a0..0c55764d6e 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -122,6 +122,8 @@ typedef struct x2ap_register_enb_req_s { * CC Params */ int16_t eutra_band[MAX_NUM_CCs]; + int32_t nr_band[MAX_NUM_CCs]; + int32_t nrARFCN[MAX_NUM_CCs]; uint32_t downlink_frequency[MAX_NUM_CCs]; int32_t uplink_frequency_offset[MAX_NUM_CCs]; uint32_t Nid_cell[MAX_NUM_CCs]; diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index c9d759df14..202e1caff1 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -34,6 +34,7 @@ #include "common/utils/LOG/log_extern.h" #include "assertions.h" #include "gnb_config.h" +#include "gnb_paramdef.h" #include "UTIL/OTG/otg.h" #include "UTIL/OTG/otg_externs.h" #include "intertask_interface.h" @@ -233,8 +234,8 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] |= curr_bit<ssb_PositionsInBurst->choice.mediumBitmap.size = 1; - scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; + scc->ssb_PositionsInBurst->choice.mediumBitmap.size = 1; + scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0; scc->ssb_PositionsInBurst->choice.mediumBitmap.buf = CALLOC(1,1); scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = 0; for (int i=0; i<8; i++) @@ -244,10 +245,10 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) { scc->ssb_PositionsInBurst->choice.longBitmap.bits_unused = 0; scc->ssb_PositionsInBurst->choice.longBitmap.buf = CALLOC(1,8); for (int j=0; j<8; j++) { - scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-j] = 0; + scc->ssb_PositionsInBurst->choice.longBitmap.buf[j] = 0; curr_bit = (ssbmap>>(j<<3))&(0xff); for (int i=0; i<8; i++) - scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-j] |= (((curr_bit>>(7-i))&0x01)<ssb_PositionsInBurst->choice.longBitmap.buf[j] |= (((curr_bit>>(7-i))&0x01)< 0) { // Output a list of all gNBs. @@ -1169,19 +1175,28 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) { "MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n", X2AP_REGISTER_ENB_REQ(msg_p).mnc); - X2AP_REGISTER_ENB_REQ (msg_p).num_cc = 1; - J = 0; - X2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = 78; //ccparams_nr_x2.nr_band; //78 - X2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = 3600000000; //ccparams_nr_x2.downlink_frequency; //3600000000 - X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = 0; //(unsigned int) ccparams_nr_x2.uplink_frequency_offset; //0 - X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= 0; //ccparams_nr_x2.Nid_cell; //0 - X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= 106; //ccparams_nr_x2.N_RB_DL; //106 + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); - X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD; - - //Temp out - /*X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency, ccparams_lte.N_RB_DL); - X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency + ccparams_lte.uplink_frequency_offset, ccparams_lte.N_RB_DL);*/ + config_getlist(&SCCsParamList, NULL, 0, aprefix); + if (SCCsParamList.numelt > 0) { + sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0); + config_get( SCCsParams,sizeof(SCCsParams)/sizeof(paramdef_t),aprefix); + fix_scc(scc,ssb_bitmap); + } + X2AP_REGISTER_ENB_REQ (msg_p).num_cc = SCCsParamList.numelt; + for (J = 0; J < SCCsParamList.numelt ; J++) { + X2AP_REGISTER_ENB_REQ (msg_p).nr_band[J] = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; //nr_band; //78 + X2AP_REGISTER_ENB_REQ (msg_p).nrARFCN[J] = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA; + X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; //0 + X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= *scc->physCellId; //0 + X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;//106 + X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD; + LOG_I(X2AP, "gNB configuration parameters: nr_band: %d, nr_ARFCN: %d, DL_RBs: %d, num_cc: %d \n", + X2AP_REGISTER_ENB_REQ (msg_p).nr_band[J], + X2AP_REGISTER_ENB_REQ (msg_p).nrARFCN[J], + X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J], + X2AP_REGISTER_ENB_REQ (msg_p).num_cc); + } sprintf(aprefix,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k); config_getlist( &X2ParamList,X2Params,sizeof(X2Params)/sizeof(paramdef_t),aprefix); diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 1252f6c2cc..973d7d525b 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -83,6 +83,7 @@ typedef enum { /* global parameters, not under a specific section */ #define GNB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity" #define GNB_CONFIG_STRING_ACTIVE_GNBS "Active_gNBs" +#define GNB_CONFIG_PUSCH_THREADS "Num_Threads_PUSCH" /*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* global configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -91,6 +92,11 @@ typedef enum { {GNB_CONFIG_STRING_ASN1_VERBOSITY, NULL, 0, uptr:NULL, defstrval:GNB_CONFIG_STRING_ASN1_VERBOSITY_NONE, TYPE_STRING, 0}, \ {GNB_CONFIG_STRING_ACTIVE_GNBS, NULL, 0, uptr:NULL, defstrval:NULL, TYPE_STRINGLIST, 0} \ } + +#define NUM_THREADS_DESC { \ +{GNB_CONFIG_PUSCH_THREADS, NULL, 0, uptr:&num_threads_pusch, defuintval:1, TYPE_UINT, 0} \ +} + #define GNB_ASN1_VERBOSITY_IDX 0 #define GNB_ACTIVE_GNBS_IDX 1 @@ -119,30 +125,6 @@ typedef enum { #define GNB_CONFIG_STRING_PUCCHTARGETPOWX10 "pucch_TargetSNRx10" #define GNB_CONFIG_STRING_NR_CELLID "nr_cellid" - -typedef struct ccparams_nr_x2 { - char *frame_type; - int32_t tdd_config; - int32_t tdd_config_s; - int32_t nr_band; - long long int downlink_frequency; - int32_t uplink_frequency_offset; - int32_t Nid_cell; - int32_t N_RB_DL; - } ccparams_nr_x2_t; - - -#define CCPARAMS_NR_X2_DESC(ccparams) { \ - {ENB_CONFIG_STRING_FRAME_TYPE, NULL, 0, strptr:&ccparams.frame_type, defstrval:"TDD", TYPE_STRING, 0}, \ - {ENB_CONFIG_STRING_TDD_CONFIG, NULL, 0, iptr:&ccparams.tdd_config, defintval:3, TYPE_UINT, 0}, \ - {ENB_CONFIG_STRING_TDD_CONFIG_S, NULL, 0, iptr:&ccparams.tdd_config_s, defintval:0, TYPE_UINT, 0}, \ - {ENB_CONFIG_STRING_EUTRA_BAND, NULL, 0, iptr:&ccparams.nr_band, defintval:78, TYPE_UINT, 0}, \ - {ENB_CONFIG_STRING_DOWNLINK_FREQUENCY, NULL, 0, i64ptr:(int64_t *)&ccparams.downlink_frequency, defint64val:3600000000, TYPE_UINT64, 0}, \ - {ENB_CONFIG_STRING_UPLINK_FREQUENCY_OFFSET, NULL, 0, iptr:&ccparams.uplink_frequency_offset, defintval:0, TYPE_INT, 0}, \ - {ENB_CONFIG_STRING_NID_CELL, NULL, 0, iptr:&ccparams.Nid_cell, defintval:0, TYPE_UINT, 0}, \ - {ENB_CONFIG_STRING_N_RB_DL, NULL, 0, iptr:&ccparams.N_RB_DL, defintval:106, TYPE_UINT, 0} \ -} - /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 8f5aab99a7..9a00fa1184 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -914,7 +914,9 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, #if (!defined(PRE_SCD_THREAD)) if (!NODE_IS_DU(RC.rrc[module_idP]->node_type)) { + void rlc_tick(int, int); PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, subframeP, module_idP); + rlc_tick(frameP, subframeP); pdcp_run(&ctxt); pdcp_mbms_run(&ctxt); rrc_rx_tx(&ctxt, CC_id); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 997fc6691e..b62df74082 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -182,7 +182,7 @@ rx_sdu(const module_id_t enb_mod_idP, UE_template_ptr->scheduled_ul_bytes = 0; } } else { // sduP == NULL => error - LOG_W(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d ULSCH in error in round %d, ul_cqi %d, UE_id %d, RNTI %x (len %d)\n", + LOG_D(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d ULSCH in error in round %d, ul_cqi %d, UE_id %d, RNTI %x (len %d)\n", enb_mod_idP, harq_pid, CC_idP, diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index e97f1bebdd..8c4ee72380 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -3099,6 +3099,9 @@ ue_scheduler(const module_id_t module_idP, } } + void rlc_tick(int, int); + rlc_tick(rxFrameP % 1024, rxSubframeP); + //#endif UE_mac_inst[module_idP].txFrame = txFrameP; UE_mac_inst[module_idP].txSubframe = txSubframeP; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 9a5946498d..876fef9dbc 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -937,14 +937,22 @@ int64_t table_6_3_3_2_4_prachConfig_Index [256][10] = { int get_format0(uint8_t index, - uint8_t unpaired){ + uint8_t unpaired, + frequency_range_t frequency_range){ uint16_t format; - if (unpaired) - format = table_6_3_3_2_3_prachConfig_Index[index][0]; - else - format = table_6_3_3_2_2_prachConfig_Index[index][0]; - + if (unpaired) { + if (frequency_range==FR1) + format = table_6_3_3_2_3_prachConfig_Index[index][0]; + else + format = table_6_3_3_2_4_prachConfig_Index[index][0]; + } + else { + if (frequency_range==FR1) + format = table_6_3_3_2_2_prachConfig_Index[index][0]; + else + AssertFatal(0==1,"no paired spectrum for FR2\n"); + } return format; } @@ -1402,11 +1410,12 @@ uint16_t table_63313[838] = { uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, uint8_t nb_preambles, - uint8_t unpaired) { + uint8_t unpaired, + frequency_range_t frequency_range) { uint8_t config_index = rach_config->rach_ConfigGeneric.prach_ConfigurationIndex; uint8_t ncs_index = rach_config->rach_ConfigGeneric.zeroCorrelationZoneConfig; - uint16_t format0 = get_format0(config_index, unpaired); + uint16_t format0 = get_format0(config_index, unpaired, frequency_range); uint16_t NCS = get_NCS(ncs_index, format0, rach_config->restrictedSetConfig); uint16_t L_ra = (rach_config->prach_RootSequenceIndex.present==NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139) ? 139 : 839; uint16_t r,u,index,q,d_u,n_shift_ra,n_shift_ra_bar,d_start; @@ -1879,7 +1888,8 @@ void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, } uint8_t N_sh_symb = pdsch_rel15->NrOfSymbols; uint8_t Imcs = pdsch_rel15->mcsIndex[0]; - uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS - N_PRB_oh; + uint16_t dmrs_length = get_num_dmrs(pdsch_rel15->dlDmrsSymbPos); + uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS*dmrs_length - N_PRB_oh; LOG_D(MAC, "N_RE_prime %d for %d symbols %d DMRS per PRB and %d overhead\n", N_RE_prime, N_sh_symb, N_PRB_DMRS, N_PRB_oh); uint16_t R; @@ -1896,10 +1906,10 @@ void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, TBS = nr_compute_tbs(Qm, R, - pdsch_rel15->rbSize, - N_sh_symb, - N_PRB_DMRS, // FIXME // This should be multiplied by the number of dmrs symbols - N_PRB_oh, + pdsch_rel15->rbSize, + N_sh_symb, + N_PRB_DMRS*dmrs_length, + N_PRB_oh, tb_scaling, pdsch_rel15->nrOfLayers)>>3; @@ -2784,6 +2794,8 @@ int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,i if (NrOfSymbols < 13 && *dmrs_config->dmrs_AdditionalPosition!=NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0) return(1<dmrs_AdditionalPosition!=NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0) return(1<dmrs_AdditionalPosition!=NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1) return(1<dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0) return(1<dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1) return(1<dmrs_DownlinkForPDSCH_MappingTypeB && @@ -2846,3 +2858,72 @@ int binomial(int n, int k) { return c; } +/* extract PTRS values from RC and validate it based upon 38.214 5.1.6.3 */ +bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, + uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs, + uint8_t *portIndex,uint8_t *nERatio, uint8_t *reOffset, + uint8_t NrOfSymbols) +{ + bool valid = true; + + /* as defined in T 38.214 5.1.6.3 */ + if(rbSize < 3) { + valid = false; + return valid; + } + /* Check for Frequency Density values */ + if(ptrs_config->frequencyDensity->list.count < 2) { + /* Default value for K_PTRS = 2 as defined in T 38.214 5.1.6.3 */ + *K_ptrs = 2; + } + else { + *K_ptrs = get_K_ptrs(*ptrs_config->frequencyDensity->list.array[0], + *ptrs_config->frequencyDensity->list.array[1], + rbSize); + } + /* Check for time Density values */ + if(ptrs_config->timeDensity->list.count < 3) { + /* Default value for L_PTRS = 1 as defined in T 38.214 5.1.6.3 */ + *L_ptrs = 1; + } + else { + *L_ptrs = get_L_ptrs(*ptrs_config->timeDensity->list.array[0], + *ptrs_config->timeDensity->list.array[1], + *ptrs_config->timeDensity->list.array[2], + mcsIndex, + mcsTable); + } + *portIndex =*ptrs_config->epre_Ratio; + *nERatio = *ptrs_config->resourceElementOffset; + *reOffset = 0; + /* If either or both of the parameters PT-RS time density (LPT-RS) and PT-RS frequency density (KPT-RS), shown in Table + * 5.1.6.3-1 and Table 5.1.6.3-2, indicates that 'PT-RS not present', the UE shall assume that PT-RS is not present + */ + if(*K_ptrs ==2 || *K_ptrs ==4 ) { + valid = true; + } + else { + valid = false; + return valid; + } + if(*L_ptrs ==0 || *L_ptrs ==1 || *L_ptrs ==2 ) { + valid = true; + } + else { + valid = false; + return valid; + } + /* PTRS is not present also : + * When the UE is receiving a PDSCH with allocation duration of 4 symbols and if LPT-RS is set to 4, the UE shall assume + * PT-RS is not transmitted + * When the UE is receiving a PDSCH with allocation duration of 2 symbols as defined in Clause 7.4.1.1.2 of [4, TS + * 38.211] and if LPT-RS is set to 2 or 4, the UE shall assume PT-RS is not transmitted. + */ + if((NrOfSymbols == 4 && *L_ptrs ==2) || ((NrOfSymbols == 2 && *L_ptrs > 0))) { + valid = false; + return valid; + } + //printf("[MAC] PTRS is set K= %u L= %u\n", *K_ptrs,1<<*L_ptrs); + return valid; +} diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index f31723a7d6..2be97ba8f6 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -44,6 +44,11 @@ #define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot #define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot +typedef enum frequency_range_e { + FR1 = 0, + FR2 +} frequency_range_t; + // PRACH occasion details typedef struct prach_occasion_info { uint8_t start_symbol; // 0 - 13 (14 symbols in a slot) @@ -159,11 +164,12 @@ uint8_t get_pusch_mcs_table(long *mcs_Table, uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, uint8_t nb_preambles, - uint8_t unpaired); + uint8_t unpaired, + frequency_range_t); int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPrecoder); -int get_format0(uint8_t index, uint8_t unpaired); +int get_format0(uint8_t index, uint8_t unpaired,frequency_range_t); int64_t *get_prach_config_info(uint32_t pointa, uint8_t index, @@ -179,4 +185,10 @@ uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB); int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH); + +bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config, + uint16_t rbSize, uint8_t mcsIndex, uint8_t mcsTable, + uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex, + uint8_t *nERatio,uint8_t *reOffset, + uint8_t NrOfSymbols); #endif diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h index 5c714e4a93..6f2b0f89fc 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h @@ -37,6 +37,8 @@ /*#include "PHY/defs_common.h"*/ +extern const uint8_t nr_slots_per_frame[5]; + /* extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE]; extern const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE]; extern const uint8_t cqi2fmt0_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE]; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 7f98af2453..66308e46fe 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -147,7 +147,6 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; NR_ServingCellConfigCommon_t *scc = mac->scc; int i; - lte_frame_type_t frame_type; mac->phy_config.Mod_id = module_id; mac->phy_config.CC_id = cc_idP; @@ -201,6 +200,10 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, } } + uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + frequency_range_t frequency_range = band<100?FR1:FR2; + + lte_frame_type_t frame_type; get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type); // cell config @@ -236,8 +239,8 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, cfg->ssb_table.ssb_mask_list[0].ssb_mask = 0; cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0; for (i=0; i<4; i++) { - cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[3-i]<ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-i]<prach_config.num_prach_fd_occasions_list[i].k1 = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart; cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig; - cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, frame_type); + cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup, nb_preambles, frame_type,frequency_range); //cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences = ??? } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index e97695e201..6d9904c94b 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -205,7 +205,7 @@ typedef struct { /// Random-access procedure flag uint8_t RA_active; /// Random-access window counter - int8_t RA_window_cnt; + int16_t RA_window_cnt; /// Random-access Msg3 size in bytes uint8_t RA_Msg3_size; /// Random-access prachMaskIndex @@ -292,10 +292,6 @@ typedef enum channel_bandwidth_e { bw_100MHz = 0x32 } channel_bandwidth_t; -typedef enum frequency_range_e { - FR1 = 0, - FR2 -} frequency_range_t; typedef struct { uint8_t identifier_dci_formats ; // 0 IDENTIFIER_DCI_FORMATS: diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 20e73073b9..18ad3526b3 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -37,8 +37,6 @@ #include "assertions.h" #include "PHY/types.h" #include "PHY/defs_UE.h" -#include "openair2/LAYER2/RLC/rlc.h" -#include "openair2/LAYER2/PDCP_v10.1.0/pdcp.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "executables/softmodem-common.h" @@ -56,11 +54,9 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) nr_rrc_mac_config_req_ue(0,0,0,NULL,rrc_inst->cell_group_config); if (IS_SOFTMODEM_NOS1){ - if (rlc_module_init(0) != 0) { - LOG_I(RLC, "Problem at RLC initiation \n"); - } + AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); pdcp_layer_init(); - nr_DRB_preconfiguration(); + nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); } // Allocate memory for ul_config_request in the mac instance. This is now a pointer and will diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 34b6d801c5..be3d7e9e75 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -63,7 +63,6 @@ #include "LAYER2/NR_MAC_UE/mac_proto.h" extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; -extern const uint8_t nr_slots_per_frame[5]; //extern uint8_t nfapi_mode; 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 36a4c5fceb..7acae47204 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -287,7 +287,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl if (ss->searchSpaceType->choice.ue_Specific){ if(ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_1_And_1_1){ // Monitors DCI 01 and 11 scrambled with C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI - if (get_softmodem_params()->phy_test == 1 && mac->crnti > 0) { + if ((mac->ra_state == RA_SUCCEEDED || get_softmodem_params()->phy_test) && mac->crnti > 0) { LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in the user specific search space\n"); rel15->num_dci_options = 2; rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_1; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index f3935d9269..9ccc65aca7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -142,7 +142,6 @@ static ssb_list_info_t ssb_list; extern int bwp_id; extern dci_pdu_rel15_t *def_dci_pdu_rel15; -extern const uint8_t nr_slots_per_frame[5]; extern void mac_rlc_data_ind ( const module_id_t module_idP, @@ -971,35 +970,30 @@ int8_t nr_ue_decode_mib(module_id_t module_id, uint16_t frame_number_4lsb = 0; for (int i=0; i<4; i++) frame_number_4lsb |= ((extra_bits>>i)&1)<<(3-i); - //uint8_t half_frame_bit = ( extra_bits >> 4 ) & 0x1; // extra bits[4] + uint8_t half_frame_bit = ( extra_bits >> 4 ) & 0x1; // extra bits[4] uint8_t ssb_subcarrier_offset_msb = ( extra_bits >> 5 ) & 0x1; // extra bits[5] uint8_t ssb_subcarrier_offset = (uint8_t)mac->mib->ssb_SubcarrierOffset; - //uint32_t ssb_index = 0; // TODO: ssb_index should obtain from L1 in case Lssb != 64 - frame = frame << 4; frame = frame | frame_number_4lsb; - if(ssb_length == 64){ - ssb_index = ssb_index & (( extra_bits >> 2 ) & 0x1C ); // { extra_bits[5:7], ssb_index[2:0] } + for (int i=0; i<3; i++) + ssb_index += (((extra_bits>>(7-i))&0x01)<<(3+i)); }else{ if(ssb_subcarrier_offset_msb){ ssb_subcarrier_offset = ssb_subcarrier_offset | 0x10; } } -#ifdef DEBUG_MIB - LOG_I(MAC,"system frame number(6 MSB bits): %d\n", mac->mib->systemFrameNumber.buf[0]); - LOG_I(MAC,"system frame number(with LSB): %d\n", (int)frame); - LOG_I(MAC,"subcarrier spacing (0=15or60, 1=30or120): %d\n", (int)mac->mib->subCarrierSpacingCommon); - LOG_I(MAC,"ssb carrier offset(with MSB): %d\n", (int)ssb_subcarrier_offset); - LOG_I(MAC,"dmrs type A position (0=pos2,1=pos3): %d\n", (int)mac->mib->dmrs_TypeA_Position); - LOG_I(MAC,"pdcch config sib1: %d\n", (int)mac->mib->pdcch_ConfigSIB1); - LOG_I(MAC,"cell barred (0=barred,1=notBarred): %d\n", (int)mac->mib->cellBarred); - LOG_I(MAC,"intra frequency reselection (0=allowed,1=notAllowed): %d\n", (int)mac->mib->intraFreqReselection); - LOG_I(MAC,"half frame bit(extra bits): %d\n", (int)half_frame_bit); - LOG_I(MAC,"ssb index(extra bits): %d\n", (int)ssb_index); -#endif + LOG_D(MAC,"system frame number(6 MSB bits): %d\n", mac->mib->systemFrameNumber.buf[0]); + LOG_D(MAC,"system frame number(with LSB): %d\n", (int)frame); + LOG_D(MAC,"subcarrier spacing (0=15or60, 1=30or120): %d\n", (int)mac->mib->subCarrierSpacingCommon); + LOG_D(MAC,"ssb carrier offset(with MSB): %d\n", (int)ssb_subcarrier_offset); + LOG_D(MAC,"dmrs type A position (0=pos2,1=pos3): %d\n", (int)mac->mib->dmrs_TypeA_Position); + LOG_D(MAC,"cell barred (0=barred,1=notBarred): %d\n", (int)mac->mib->cellBarred); + LOG_D(MAC,"intra frequency reselection (0=allowed,1=notAllowed): %d\n", (int)mac->mib->intraFreqReselection); + LOG_D(MAC,"half frame bit(extra bits): %d\n", (int)half_frame_bit); + LOG_D(MAC,"ssb index(extra bits): %d\n", (int)ssb_index); subcarrier_spacing_t scs_ssb = scs_30kHz; // default for //const uint32_t scs_index = 0; @@ -1022,8 +1016,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, int32_t num_rbs = -1; int32_t num_symbols = -1; int32_t rb_offset = -1; - //LOG_I(MAC,"<<<<<<<<mib->pdcch_ConfigSIB1,index_4msb,index_4lsb,scs_ssb,scs_pdcch, (scs_ssb << 5)|scs_pdcch); + LOG_D(MAC,"<<<<<<<<scc->tdd_UL_DL_ConfigurationCommon->pattern1; const int num_slots_per_tdd = nr_slots_per_frame[mu] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity); const int num_slots_ul = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0); - int index = slot + num_slots_ul - num_slots_per_tdd; + int index = (slot + num_slots_ul - num_slots_per_tdd) % num_slots_per_tdd; LOG_D(MAC, "nr_ue_procedures: get_ul_config_request() slots per tdd %d, num_slots_ul %d, index %d\n", num_slots_per_tdd, num_slots_ul, @@ -1507,8 +1501,10 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in } } else if (ul_info) { - // ULSCH is handled only in phy-test mode (consistently with OAI gNB) - if (get_softmodem_params()->phy_test) { + module_id_t mod_id = ul_info->module_id; + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + + if (mac->ra_state == RA_SUCCEEDED || get_softmodem_params()->phy_test) { uint8_t nb_dmrs_re_per_rb; uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; @@ -1517,14 +1513,12 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in uint32_t TBS; int i, N_PRB_oh; - module_id_t mod_id = ul_info->module_id; uint32_t gNB_index = ul_info->gNB_index; int cc_id = ul_info->cc_id; frame_t rx_frame = ul_info->frame_rx; slot_t rx_slot = ul_info->slot_rx; frame_t frame_tx = ul_info->frame_tx; slot_t slot_tx = ul_info->slot_tx; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); uint8_t access_mode = SCHEDULED_ACCESS; fapi_nr_ul_config_request_t *ul_config_req = get_ul_config_request(mac, slot_tx); @@ -2896,6 +2890,13 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p dlsch_config_pdu->number_rbs = NRRIV2BW(riv,n_RB_DLBWP); dlsch_config_pdu->start_rb = NRRIV2PRBOFFSET(riv,n_RB_DLBWP); + // Sanity check in case a false or erroneous DCI is received + if ((dlsch_config_pdu->number_rbs < 1 ) || (dlsch_config_pdu->number_rbs > n_RB_DLBWP - dlsch_config_pdu->start_rb)) { + // DCI is invalid! + LOG_W(MAC, "Frequency domain assignment values are invalid! #RBs: %d, Start RB: %d, n_RB_DLBWP: %d \n", dlsch_config_pdu->number_rbs, dlsch_config_pdu->start_rb, n_RB_DLBWP); + return -1; + } + } if(pusch_config_pdu != NULL){ /* @@ -2910,6 +2911,14 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p pusch_config_pdu->rb_size = NRRIV2BW(riv,n_RB_ULBWP); pusch_config_pdu->rb_start = NRRIV2PRBOFFSET(riv,n_RB_ULBWP); + + // Sanity check in case a false or erroneous DCI is received + if ((pusch_config_pdu->rb_size < 1) || (pusch_config_pdu->rb_size > n_RB_ULBWP - pusch_config_pdu->rb_start)) { + // DCI is invalid! + LOG_W(MAC, "Frequency domain assignment values are invalid! #RBs: %d, Start RB: %d, n_RB_ULBWP: %d \n",pusch_config_pdu->rb_size, pusch_config_pdu->rb_start, n_RB_ULBWP); + return -1; + } + } return 0; } @@ -3133,8 +3142,9 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr int bwp_id = 1; int mu = 0; long k2 = 0; + int pucch_res_set_cnt = 0, valid = 0; uint16_t frame_tx = 0, slot_tx = 0; - + bool valid_ptrs_setup = 0; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; fapi_nr_ul_config_request_t *ul_config = NULL; @@ -3194,7 +3204,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu_0_0 = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu; /* IDENTIFIER_DCI_FORMATS */ /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ - nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val); + if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val) < 0) + return -1; /* TIME_DOM_RESOURCE_ASSIGNMENT */ if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_0,NULL,dci->time_domain_assignment.val) < 0) return -1; @@ -3205,6 +3216,27 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* MCS */ pusch_config_pdu_0_0->mcs_index = dci->mcs; + + /* MCS TABLE */ + if (mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) + pusch_config_pdu_0_0->transform_precoding = 1; + else + pusch_config_pdu_0_0->transform_precoding = 0; + + if (pusch_config_pdu_0_0->transform_precoding == transform_precoder_disabled) + pusch_config_pdu_0_0->mcs_table = get_pusch_mcs_table(pusch_config->mcs_Table, 0, + dci_format, NR_RNTI_TC, NR_SearchSpace__searchSpaceType_PR_common, false); + else + pusch_config_pdu_0_0->mcs_table = get_pusch_mcs_table(pusch_config->mcs_TableTransformPrecoder, 1, + dci_format, NR_RNTI_TC, NR_SearchSpace__searchSpaceType_PR_common, false); + + pusch_config_pdu_0_0->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu_0_0->mcs_index, pusch_config_pdu_0_0->mcs_table); + pusch_config_pdu_0_0->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu_0_0->mcs_index, pusch_config_pdu_0_0->mcs_table); + if (pusch_config_pdu_0_0->target_code_rate == 0 || pusch_config_pdu_0_0->qam_mod_order == 0) { + LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected UL DCI. Ignoring DCI! \n"); + return -1; + } + /* NDI */ pusch_config_pdu_0_0->pusch_data.new_data_indicator = dci->ndi; /* RV */ @@ -3293,7 +3325,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* BANDWIDTH_PART_IND */ //pusch_config_pdu_0_1->bandwidth_part_ind = dci->bwp_indicator.val; /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ - nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val); + if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val) < 0) + return -1; /* TIME_DOM_RESOURCE_ASSIGNMENT */ if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL,dci->time_domain_assignment.val) < 0) return -1; @@ -3651,7 +3684,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->SubcarrierSpacing = mac->DLbwp[0]->bwp_Common->genericParameters.subcarrierSpacing; /* IDENTIFIER_DCI_FORMATS */ /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ - nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,n_RB_DLBWP,dci->frequency_domain_assignment.val); + if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,n_RB_DLBWP,dci->frequency_domain_assignment.val) < 0) + return -1; /* TIME_DOM_RESOURCE_ASSIGNMENT */ if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val) < 0) return -1; @@ -3667,8 +3701,15 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 2; /* VRB_TO_PRB_MAPPING */ dlsch_config_pdu_1_0->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; + /* MCS TABLE INDEX */ + dlsch_config_pdu_1_0->mcs_table = (pdsch_config->mcs_Table) ? (*pdsch_config->mcs_Table + 1) : 0; /* MCS */ dlsch_config_pdu_1_0->mcs = dci->mcs; + // Basic sanity check for MCS value to check for a false or erroneous DCI + if (dlsch_config_pdu_1_0->mcs > 28) { + LOG_W(MAC, "MCS value % d out of bounds! Possibly due to false DCI. Ignoring DCI!!\n", dlsch_config_pdu_1_0->mcs); + return -1; + } /* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ dlsch_config_pdu_1_0->ndi = dci->ndi; /* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ @@ -3699,6 +3740,20 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr //if (dci->pucch_resource_indicator == 6) dlsch_config_pdu_1_0->pucch_resource_id = 7; //pucch-ResourceId obtained from the 7th value of resourceList FIXME!! //if (dci->pucch_resource_indicator == 7) dlsch_config_pdu_1_0->pucch_resource_id = 8; //pucch-ResourceId obtained from the 8th value of resourceList FIXME!! dlsch_config_pdu_1_0->pucch_resource_id = dci->pucch_resource_indicator; + // Sanity check for pucch_resource_indicator value received to check for false DCI. + valid = 0; + pucch_res_set_cnt = mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.count; + for (int id = 0; id < pucch_res_set_cnt; id++) { + if (dlsch_config_pdu_1_0->pucch_resource_id < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { + valid = 1; + break; + } + } + if (!valid) { + LOG_W(MAC, "pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", dlsch_config_pdu_1_0->pucch_resource_id); + return -1; + } + /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI)*/ dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind = dci->pdsch_to_harq_feedback_timing_indicator.val; @@ -3776,7 +3831,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* BANDWIDTH_PART_IND */ // dlsch_config_pdu_1_1->bandwidth_part_ind = dci->bandwidth_part_ind; /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ - nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val); + if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val) < 0) + return -1; /* TIME_DOM_RESOURCE_ASSIGNMENT */ if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val) < 0) return -1; @@ -3799,12 +3855,22 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_1->zp_csi_rs_trigger = dci->zp_csi_rs_trigger.val; /* MCS (for transport block 1)*/ dlsch_config_pdu_1_1->mcs = dci->mcs; + // Basic sanity check for MCS value to check for a false or erroneous DCI + if (dlsch_config_pdu_1_1->mcs > 28) { + LOG_W(MAC, "MCS value % d out of bounds! Possibly due to false DCI. Ignoring DCI!!\n", dlsch_config_pdu_1_1->mcs); + return -1; + } /* NDI (for transport block 1)*/ dlsch_config_pdu_1_1->ndi = dci->ndi; /* RV (for transport block 1)*/ dlsch_config_pdu_1_1->rv = dci->rv; /* MCS (for transport block 2)*/ dlsch_config_pdu_1_1->tb2_mcs = dci->mcs2.val; + // Basic sanity check for MCS value to check for a false or erroneous DCI + if (dlsch_config_pdu_1_1->tb2_mcs > 28) { + LOG_W(MAC, "MCS value % d out of bounds! Possibly due to false DCI. Ignoring DCI!!\n", dlsch_config_pdu_1_1->tb2_mcs); + return -1; + } /* NDI (for transport block 2)*/ dlsch_config_pdu_1_1->tb2_ndi = dci->ndi2.val; /* RV (for transport block 2)*/ @@ -3821,6 +3887,20 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr if (dci->tpc == 3) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 3; /* PUCCH_RESOURCE_IND */ dlsch_config_pdu_1_1->pucch_resource_id = dci->pucch_resource_indicator; + // Sanity check for pucch_resource_indicator value received to check for false DCI. + valid = 0; + pucch_res_set_cnt = mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.count; + for (int id = 0; id < pucch_res_set_cnt; id++) { + if (dlsch_config_pdu_1_1->pucch_resource_id < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) { + valid = 1; + break; + } + } + if (!valid) { + LOG_W(MAC, "pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", dlsch_config_pdu_1_1->pucch_resource_id); + return -1; + } + /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ // according to TS 38.213 Table 9.2.3-1 dlsch_config_pdu_1_1->pdsch_to_harq_feedback_time_ind = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; @@ -3925,6 +4005,19 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); dl_config->number_pdus = dl_config->number_pdus + 1; + /* TODO same calculation for MCS table as done in UL */ + dlsch_config_pdu_1_1->mcs_table = (pdsch_config->mcs_Table) ? (*pdsch_config->mcs_Table + 1) : 0; + /*PTRS configuration */ + if(mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) { + valid_ptrs_setup = set_dl_ptrs_values(mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup, + dlsch_config_pdu_1_1->number_rbs, dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table, + &dlsch_config_pdu_1_1->PTRSFreqDensity,&dlsch_config_pdu_1_1->PTRSTimeDensity, + &dlsch_config_pdu_1_1->PTRSPortIndex,&dlsch_config_pdu_1_1->nEpreRatioOfPDSCHToPTRS, + &dlsch_config_pdu_1_1->PTRSReOffset, dlsch_config_pdu_1_1->number_symbols); + if(valid_ptrs_setup==true) { + dlsch_config_pdu_1_1->pduBitmap |= 0x1; + } + } break; @@ -4842,7 +4935,7 @@ void nr_ue_process_mac_pdu(module_id_t module_idP, if (rx_lcid < NB_RB_MAX && rx_lcid >= DL_SCH_LCID_DTCH) { mac_rlc_data_ind(module_idP, - 0x1234, + mac->crnti, gNB_index, frameP, ENB_FLAG_NO, @@ -5054,6 +5147,7 @@ nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t ulsch_sdus[MAX_ULSCH_PAYLOAD_BYTES]; uint16_t sdu_length_total = 0; //unsigned short post_padding = 0; + NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); rlc_buffer_occupancy_t lcid_buffer_occupancy_old = 0, lcid_buffer_occupancy_new = 0; @@ -5066,19 +5160,12 @@ nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, start_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu); #endif - //NR_UE_MAC_INST_t *nr_ue_mac_inst = get_mac_inst(0); - // Check for DCCH first // TO DO: Multiplex in the order defined by the logical channel prioritization for (lcid = UL_SCH_LCID_SRB1; lcid < NR_MAX_NUM_LCID; lcid++) { - lcid_buffer_occupancy_old = - //TODO: Replace static value with CRNTI - mac_rlc_get_buffer_occupancy_ind(module_idP, - 0x1234, eNB_index, frameP, //nr_ue_mac_inst->crnti - subframe, ENB_FLAG_NO, - lcid); + lcid_buffer_occupancy_old = mac_rlc_get_buffer_occupancy_ind(module_idP, mac->crnti, eNB_index, frameP, subframe, ENB_FLAG_NO, lcid); lcid_buffer_occupancy_new = lcid_buffer_occupancy_old; if(lcid_buffer_occupancy_new){ @@ -5094,17 +5181,17 @@ nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, while(buflen_remain > 0 && lcid_buffer_occupancy_new){ - //TODO: Replace static value with CRNTI sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - 0x1234, eNB_index, //nr_ue_mac_inst->crnti + mac->crnti, + eNB_index, frameP, ENB_FLAG_NO, MBMS_FLAG_NO, lcid, buflen_remain, (char *)&ulsch_sdus[sdu_length_total],0, - 0 - ); + 0); + AssertFatal(buflen_remain >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", lcid, sdu_lengths[num_sdus], buflen_remain); @@ -5120,14 +5207,13 @@ nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, } /* Get updated BO after multiplexing this PDU */ - //TODO: Replace static value with CRNTI - - lcid_buffer_occupancy_new = - mac_rlc_get_buffer_occupancy_ind(module_idP, - 0x1234, //nr_ue_mac_inst->crnti - eNB_index, frameP, - subframe, ENB_FLAG_NO, - lcid); + lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP, + mac->crnti, + eNB_index, + frameP, + subframe, + ENB_FLAG_NO, + lcid); buflen_remain = buflen - (total_rlc_pdu_header_len + sdu_length_total + MAX_RLC_SDU_SUBHEADER_SIZE); } @@ -5143,7 +5229,7 @@ nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, sdu_lengths, // sdu length sdu_lcids, // sdu lcid 0, // power_headroom - 0, // crnti + mac->crnti, // crnti 0, // truncated_bsr 0, // short_bsr 0, // long_bsr diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index ab49fcdc8c..a751529985 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -124,6 +124,9 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm } } + uint32_t band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + frequency_range_t frequency_range = band<100?FR1:FR2; + lte_frame_type_t frame_type; get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing, &frame_type); RC.nrmac[Mod_idP]->common_channels[0].frame_type = frame_type; @@ -213,7 +216,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf.value = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig; cfg->prach_config.num_prach_fd_occasions_list[i].prach_zero_corr_conf.tl.tag = NFAPI_NR_CONFIG_PRACH_ZERO_CORR_CONF_TAG; cfg->num_tlv++; - cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.value = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup,nb_preambles, frame_type); + cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.value = compute_nr_root_seq(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup,nb_preambles, frame_type, frequency_range); cfg->prach_config.num_prach_fd_occasions_list[i].num_root_sequences.tl.tag = NFAPI_NR_CONFIG_NUM_ROOT_SEQUENCES_TAG; cfg->num_tlv++; cfg->prach_config.num_prach_fd_occasions_list[i].num_unused_root_sequences.value = 1; @@ -252,8 +255,8 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm cfg->ssb_table.ssb_mask_list[0].ssb_mask.value = 0; cfg->ssb_table.ssb_mask_list[1].ssb_mask.value = 0; for (i=0; i<4; i++) { - cfg->ssb_table.ssb_mask_list[0].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<ssb_table.ssb_mask_list[1].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<ssb_table.ssb_mask_list[0].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[3-i]<ssb_table.ssb_mask_list[1].ssb_mask.value += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[7-i]<ssb_PositionsInBurst->present > 0) && (scc->ssb_PositionsInBurst->present < 4), "SSB Bitmap type %d is not valid\n",scc->ssb_PositionsInBurst->present); + /* dimension UL_tti_req_ahead for number of slots in frame */ + const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160}; + const int n = slots_per_frame[*scc->ssbSubcarrierSpacing]; + RC.nrmac[Mod_idP]->UL_tti_req_ahead[0] = calloc(n, sizeof(nfapi_nr_ul_tti_request_t)); + AssertFatal(RC.nrmac[Mod_idP]->UL_tti_req_ahead[0], + "could not allocate memory for RC.nrmac[]->UL_tti_req_ahead[]\n"); + /* fill in slot/frame numbers: slot is fixed, frame will be updated by + * scheduler */ + for (int i = 0; i < n; ++i) { + nfapi_nr_ul_tti_request_t *req = &RC.nrmac[Mod_idP]->UL_tti_req_ahead[0][i]; + /* consider that scheduler runs sl_ahead: the first sl_ahead slots are + * already "in the past" and thus we put frame 1 instead of 0! Note that + * variable sl_ahead seems to not be correctly initialized, but I leave + * it for information purposes here (the fix would always put 0, what + * happens now, too) */ + req->SFN = i < sl_ahead; + req->Slot = i; + } + + RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL = + calloc(n * 275, sizeof(uint16_t)); + AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL, + "could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n"); + LOG_I(MAC,"Configuring common parameters from NR ServingCellConfig\n"); config_common(Mod_idP, @@ -369,6 +397,12 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, bwpList->list.count); const int bwp_id = 1; UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1]; + struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList; + AssertFatal(ubwpList->list.count == 1, + "uplinkBWP_ToAddModList has %d BWP!\n", + ubwpList->list.count); + UE_info->UE_sched_ctrl[UE_id].active_ubwp = ubwpList->list.array[bwp_id - 1]; LOG_I(PHY,"Added new UE_id %d/%x with initial secondaryCellGroup\n",UE_id,rnti); } else if (add_ue == 1 && !get_softmodem_params()->phy_test) { /* TODO: should check for free RA process */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 5d701bf5b8..b8ed6a8cc6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -32,9 +32,7 @@ #include "assertions.h" -#include "LAYER2/MAC/mac.h" #include "NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" #include "NR_MAC_gNB/mac_proto.h" #include "common/utils/LOG/log.h" @@ -51,15 +49,10 @@ #include "openair1/PHY/defs_gNB.h" #include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h" -//Agent-related headers -#include "flexran_agent_extern.h" -#include "flexran_agent_mac.h" - #include "intertask_interface.h" #include "executables/softmodem-common.h" -const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160}; uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; void clear_mac_stats(gNB_MAC_INST *gNB) { @@ -92,9 +85,12 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, int CC_idP, frame_t frameP, sub_frame_t slotP){ + NR_ServingCellConfigCommon_t *scc = gNB->common_channels->ServingCellConfigCommon; + const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; nfapi_nr_dl_tti_request_t *DL_req = &gNB->DL_req[0]; - nfapi_nr_ul_tti_request_t *UL_tti_req = &gNB->UL_tti_req[0]; + nfapi_nr_ul_tti_request_t *future_ul_tti_req = + &gNB->UL_tti_req_ahead[CC_idP][(slotP + num_slots - 1) % num_slots]; nfapi_nr_ul_dci_request_t *UL_dci_req = &gNB->UL_dci_req[0]; nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0]; @@ -112,12 +108,17 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, UL_dci_req[CC_idP].Slot = slotP; UL_dci_req[CC_idP].numPdus = 0; - UL_tti_req[CC_idP].SFN = frameP; - UL_tti_req[CC_idP].Slot = slotP; - UL_tti_req[CC_idP].n_pdus = 0; - UL_tti_req[CC_idP].n_ulsch = 0; - UL_tti_req[CC_idP].n_ulcch = 0; - UL_tti_req[CC_idP].n_group = 0; + /* advance last round's future UL_tti_req to be ahead of current frame/slot */ + future_ul_tti_req->SFN = (slotP == 0 ? frameP : frameP + 1) % 1024; + /* future_ul_tti_req->Slot is fixed! */ + future_ul_tti_req->n_pdus = 0; + future_ul_tti_req->n_ulsch = 0; + future_ul_tti_req->n_ulcch = 0; + future_ul_tti_req->n_group = 0; + + /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e., + * it walks over UL_tti_req_ahead in a circular fashion */ + gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][slotP]; TX_req[CC_idP].Number_of_PDUs = 0; @@ -285,113 +286,6 @@ void schedule_nr_SRS(module_id_t module_idP, frame_t frameP, sub_frame_t subfram */ -/* -void copy_nr_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) -{ - int CC_id; - gNB_MAC_INST *mac = RC.nrmac[module_idP]; - - for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - - nfapi_ul_config_request_t *ul_req = &mac->UL_tti_req[CC_id]; - - *ul_req = *ul_req_tmp; - - // Restore the pointer - ul_req->ul_config_request_body.ul_config_pdu_list = ul_req_pdu; - ul_req->sfn_sf = (frameP<<7) + slotP; - ul_req_tmp->ul_config_request_body.number_of_pdus = 0; - - if (ul_req->ul_config_request_body.number_of_pdus>0) - { - LOG_D(PHY, "%s() active NOW (frameP:%d slotP:%d) pdus:%d\n", __FUNCTION__, frameP, slotP, ul_req->ul_config_request_body.number_of_pdus); - } - - memcpy((void*)ul_req->ul_config_request_body.ul_config_pdu_list, - (void*)ul_req_tmp->ul_config_request_body.ul_config_pdu_list, - ul_req->ul_config_request_body.number_of_pdus*sizeof(nfapi_ul_config_request_pdu_t)); - } -} -*/ - -void nr_schedule_pusch(int Mod_idP, - int UE_id, - int num_slots_per_tdd, - int ul_slots, - frame_t frameP, - sub_frame_t slotP) { - - nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; - NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - int k = slotP + ul_slots - num_slots_per_tdd; - NR_sched_pusch *pusch = &UE_info->UE_sched_ctrl[UE_id].sched_pusch[k]; - if ((pusch->active == true) && (frameP == pusch->frame) && (slotP == pusch->slot)) { - UL_tti_req->SFN = pusch->frame; - UL_tti_req->Slot = pusch->slot; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pusch_pdu = pusch->pusch_pdu; - UL_tti_req->n_pdus+=1; - memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pusch[k], - 0, sizeof(NR_sched_pusch)); - } -} - - -void nr_schedule_pucch(int Mod_idP, - int UE_id, - int nr_ulmix_slots, - frame_t frameP, - sub_frame_t slotP) { - - uint16_t O_csi, O_ack, O_uci; - uint8_t O_sr = 0; // no SR in PUCCH implemented for now - NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; - NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id); - - NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; - int bwp_id=1; - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; - nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; - - NR_sched_pucch *curr_pucch; - - for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l]; - O_ack = curr_pucch->dai_c; - O_csi = curr_pucch->csi_bits; - O_uci = O_ack + O_csi + O_sr; - if ((O_uci>0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) { - UL_tti_req->SFN = curr_pucch->frame; - UL_tti_req->Slot = curr_pucch->ul_slot; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE; - UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t); - nfapi_nr_pucch_pdu_t *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu; - memset(pucch_pdu,0,sizeof(nfapi_nr_pucch_pdu_t)); - UL_tti_req->n_pdus+=1; - - LOG_D(MAC,"Scheduling pucch reception for frame %d slot %d with (%d, %d, %d) (SR ACK, CSI) bits\n", - frameP,slotP,O_sr,O_ack,curr_pucch->csi_bits); - - nr_configure_pucch(pucch_pdu, - scc, - ubwp, - UE_info->rnti[UE_id], - curr_pucch->resource_indicator, - O_csi, - O_ack, - O_sr); - - memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l], - 0, - sizeof(NR_sched_pucch)); - } - } - } -} - bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { return (bitmap >> slot) & 0x01; } @@ -410,7 +304,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_UE_info_t *UE_info = &gNB->UE_info; - NR_UE_sched_ctrl_t *ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; @@ -452,7 +345,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, AssertFatal(1==0,"Undefined tdd period %ld\n", scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); } - int num_slots_per_tdd = (slots_per_frame[*scc->ssbSubcarrierSpacing])/nb_periods_per_frame; + int num_slots_per_tdd = (nr_slots_per_frame[*scc->ssbSubcarrierSpacing])/nb_periods_per_frame; const int nr_ulmix_slots = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0); @@ -479,7 +372,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // clear vrb_maps memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * 275); - memset(cc[CC_id].vrb_map_UL, 0, sizeof(uint16_t) * 275); + // clear last scheduled slot's content (only)! + const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int last_slot = (slot + num_slots - 1) % num_slots; + uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; + memset(&vrb_map_UL[last_slot * 275], 0, sizeof(uint16_t) * 275); clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot); } @@ -489,45 +386,43 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // This schedules MIB - schedule_nr_mib(module_idP, frame, slot, slots_per_frame[*scc->ssbSubcarrierSpacing]); + schedule_nr_mib(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]); // This schedule PRACH if we are not in phy_test mode - if (get_softmodem_params()->phy_test == 0) - schedule_nr_prach(module_idP, frame, slot); + if (get_softmodem_params()->phy_test == 0) { + /* we need to make sure that resources for PRACH are free. To avoid that + e.g. PUSCH has already been scheduled, make sure we schedule before + anything else: below, we simply assume an advance one frame (minus one + slot, because otherwise we would allocate the current slot in + UL_tti_req_ahead), but be aware that, e.g., K2 is allowed to be larger + (schedule_nr_prach will assert if resources are not free). */ + const sub_frame_t n_slots_ahead = nr_slots_per_frame[*scc->ssbSubcarrierSpacing] - 1; + const frame_t f = (frame + (slot + n_slots_ahead) / nr_slots_per_frame[*scc->ssbSubcarrierSpacing]) % 1024; + const sub_frame_t s = (slot + n_slots_ahead) % nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + schedule_nr_prach(module_idP, f, s); + } // This schedule SR // TODO // This schedule CSI measurement reporting if (UE_info->active[UE_id]) - nr_csi_meas_reporting(module_idP, UE_id, frame, slot, num_slots_per_tdd, nr_ulmix_slots, slots_per_frame[*scc->ssbSubcarrierSpacing]); + nr_csi_meas_reporting(module_idP, UE_id, frame, slot, num_slots_per_tdd, nr_ulmix_slots, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]); // This schedule RA procedure if not in phy_test mode // Otherwise already consider 5G already connected - RC.nrmac[module_idP]->current_slot=slot; if (get_softmodem_params()->phy_test == 0) { nr_schedule_RA(module_idP, frame, slot); - nr_schedule_reception_msg3(module_idP, 0, frame, slot); - } // This schedules the DCI for Uplink and subsequently PUSCH - - // The decision about whether to schedule is done for each UE independently - // inside - if (UE_info->active[UE_id] && slot < 10) { - - int tda = 1; // time domain assignment hardcoded for now - schedule_fapi_ul_pdu(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, tda, ulsch_in_slot_bitmap); - nr_schedule_pusch(module_idP, UE_id, num_slots_per_tdd, nr_ulmix_slots, frame, slot); + if (slot < 10) { + nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap); } - - if (UE_info->active[UE_id] - && (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot % num_slots_per_tdd)) + // This schedules the DCI for Downlink and PDSCH + if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot % num_slots_per_tdd) && slot < 10) { - - ue_sched_ctl->current_harq_pid = slot % num_slots_per_tdd; nr_schedule_ue_spec(module_idP, frame, slot, num_slots_per_tdd); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 66dcfcff86..e15963f355 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -43,6 +43,7 @@ extern RAN_CONTEXT_t RC; extern const uint8_t nr_slots_per_frame[5]; +extern uint16_t sl_ahead; uint8_t DELTA[4]= {2,3,4,6}; @@ -62,19 +63,19 @@ int16_t ssb_index_from_prach(module_id_t module_idP, nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; - uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; + uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; - uint8_t total_RApreambles = 64; - if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) + uint8_t total_RApreambles = 64; + if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL) total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles; - float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; + float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; uint16_t start_symbol_index = 0; uint8_t mu,N_dur=0,N_t_slot=0,start_symbol = 0, temp_start_symbol = 0, N_RA_slot=0; uint16_t format,RA_sfn_index = -1; - uint8_t config_period = 1; + uint8_t config_period = 1; uint16_t prach_occasion_id = -1; - uint8_t num_active_ssb = cc->num_active_ssb; + uint8_t num_active_ssb = cc->num_active_ssb; if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; @@ -95,45 +96,51 @@ int16_t ssb_index_from_prach(module_id_t module_idP, &N_RA_slot, &config_period); uint8_t index = 0,slot_index = 0; - for (slot_index = 0;slot_index < N_RA_slot; slot_index++) { + for (slot_index = 0;slot_index < N_RA_slot; slot_index++) { if (N_RA_slot <= 1) { //1 PRACH slot in a subframe if((mu == 1) || (mu == 3)) slot_index = 1; //For scs = 30khz and 120khz } for (int i=0; i< N_t_slot; i++) { temp_start_symbol = (start_symbol + i * N_dur + 14 * slot_index) % 14; - if(symbol == temp_start_symbol) { - start_symbol_index = i; - break; - } - } - } + if(symbol == temp_start_symbol) { + start_symbol_index = i; + break; + } + } + } if (N_RA_slot <= 1) { //1 PRACH slot in a subframe if((mu == 1) || (mu == 3)) slot_index = 0; //For scs = 30khz and 120khz } - -// prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index; - prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period)*cc->total_prach_occasions_per_config_period) + (RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index; -//one RO is shared by one or more SSB - if(num_ssb_per_RO <= 1 ) - index = (int) (prach_occasion_id / (int)(1/num_ssb_per_RO)) % num_active_ssb; -//one SSB have more than one continuous RO - else if ( num_ssb_per_RO > 1) { - index = (prach_occasion_id * (int)num_ssb_per_RO)% num_active_ssb ; - for(int j = 0;j < num_ssb_per_RO;j++) { - if(preamble_index < (((j+1) * total_RApreambles) / num_ssb_per_RO)) - index = index + j; - } - } - LOG_D(MAC, "Frame %d, Slot %d: Prach Occasion id = %d ssb per RO = %f number of active SSB %u index = %d fdm %u symbol index %u freq_index %u total_RApreambles %u\n", frameP, slotP, prach_occasion_id, num_ssb_per_RO, num_active_ssb, index, fdm, start_symbol_index, freq_index, total_RApreambles); + // prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index; + prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period)*cc->total_prach_occasions_per_config_period) + + (RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index; + + //one RO is shared by one or more SSB + if(num_ssb_per_RO <= 1 ) + index = (int) (prach_occasion_id / (int)(1/num_ssb_per_RO)) % num_active_ssb; + //one SSB have more than one continuous RO + else if ( num_ssb_per_RO > 1) { + index = (prach_occasion_id * (int)num_ssb_per_RO)% num_active_ssb ; + for(int j = 0;j < num_ssb_per_RO;j++) { + if(preamble_index < (((j+1) * total_RApreambles) / num_ssb_per_RO)) + index = index + j; + } + } + + LOG_D(MAC, "Frame %d, Slot %d: Prach Occasion id = %d ssb per RO = %f number of active SSB %u index = %d fdm %u symbol index %u freq_index %u total_RApreambles %u\n", + frameP, slotP, prach_occasion_id, num_ssb_per_RO, num_active_ssb, index, fdm, start_symbol_index, freq_index, total_RApreambles); + return index; } + + //Compute Total active SSBs and RO available void find_SSB_and_RO_available(module_id_t module_idP) { - gNB_MAC_INST *gNB = RC.nrmac[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]; @@ -141,7 +148,7 @@ void find_SSB_and_RO_available(module_id_t module_idP) { uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; uint8_t mu,N_dur=0,N_t_slot=0,start_symbol=0,N_RA_slot = 0; uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0; - uint8_t num_active_ssb = 0; + uint8_t num_active_ssb = 0; uint8_t max_association_period = 1; if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) @@ -151,190 +158,190 @@ void find_SSB_and_RO_available(module_id_t module_idP) { // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 get_nr_prach_occasion_info_from_index(config_index, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, - mu, - cc->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &N_RA_slot, - &N_RA_sfn, - &max_association_period); + scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, + mu, + cc->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &N_RA_slot, + &N_RA_sfn, + &max_association_period); float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; - uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; + uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ; - uint32_t total_RA_occasions = N_RA_sfn * N_t_slot * N_RA_slot * fdm; + uint32_t total_RA_occasions = N_RA_sfn * N_t_slot * N_RA_slot * fdm; - for(int i = 0;i < 64;i++) { + for(int i = 0;i < 64;i++) { if ((L_ssb >> (63-i)) & 0x01) { // only if the bit of L_ssb at current ssb index is 1 cc->ssb_index[num_active_ssb] = i; - num_active_ssb++; + num_active_ssb++; } - } + } - for(int i = 1; (1 << (i-1)) <= max_association_period;i++) { + for(int i = 1; (1 << (i-1)) <= max_association_period;i++) { if(total_RA_occasions >= (int) (num_active_ssb/num_ssb_per_RO)) { - repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb); - break; - } - else { - total_RA_occasions = total_RA_occasions * i; - cc->max_association_period = i; - } - } + repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb); + break; + } + else { + total_RA_occasions = total_RA_occasions * i; + cc->max_association_period = i; + } + } if(cc->max_association_period == 0) - cc->max_association_period = 1; + cc->max_association_period = 1; - unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO); - cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion; - cc->num_active_ssb = num_active_ssb; - - LOG_I(MAC, "Total available RO %d, num of active SSB %d: unused RO = %d max_association_period %u N_RA_sfn %u \n", cc->total_prach_occasions, cc->num_active_ssb, unused_RA_occasion, max_association_period, N_RA_sfn); + unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO); + cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion; + cc->num_active_ssb = num_active_ssb; + LOG_I(MAC, "Total available RO %d, num of active SSB %d: unused RO = %d max_association_period %u N_RA_sfn %u \n", + cc->total_prach_occasions, cc->num_active_ssb, unused_RA_occasion, max_association_period, N_RA_sfn); } -void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - +void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req[0]; + nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][slotP]; nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; if (is_nr_UL_slot(scc,slotP)) { - uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; - uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot; - uint16_t RA_sfn_index = -1; - uint8_t config_period = 1; - uint16_t format; - int slot_index = 0; - uint16_t prach_occasion_id = -1; + uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex; + uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot; + uint16_t RA_sfn_index = -1; + uint8_t config_period = 1; + uint16_t format; + int slot_index = 0; + uint16_t prach_occasion_id = -1; - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) - mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; - else - mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing) + mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing; + else + mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; - // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 - if ( get_nr_prach_info_from_index(config_index, - (int)frameP, - (int)slotP, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, - mu, - cc->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &RA_sfn_index, - &N_RA_slot, - &config_period) ) { - uint16_t format0 = format&0xff; // first column of format from table - uint16_t format1 = (format>>8)&0xff; // second column of format from table + uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; + // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 + if ( get_nr_prach_info_from_index(config_index, + (int)frameP, + (int)slotP, + scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, + mu, + cc->frame_type, + &format, + &start_symbol, + &N_t_slot, + &N_dur, + &RA_sfn_index, + &N_RA_slot, + &config_period) ) { - if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe - if (slotP%2 == 1){ - slot_index = 1; - } - else { - slot_index = 0; - } - }else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe - slot_index = 0; - } + uint16_t format0 = format&0xff; // first column of format from table + uint16_t format1 = (format>>8)&0xff; // second column of format from table + if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe + if (slotP%2 == 1) + slot_index = 1; + else + slot_index = 0; + }else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe + slot_index = 0; + } - UL_tti_req->SFN = frameP; - UL_tti_req->Slot = slotP; - for (int fdm_index=0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion - for (int td_index=0; td_indexSFN = frameP; + UL_tti_req->Slot = slotP; + for (int fdm_index=0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion + for (int td_index=0; td_indexmax_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) + (RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index; - if((prach_occasion_id < cc->total_prach_occasions) && (td_index == 0)){ + prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) + + (RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index; - 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)); - UL_tti_req->n_pdus+=1; + if((prach_occasion_id < cc->total_prach_occasions) && (td_index == 0)){ - // filling the prach fapi structure - prach_pdu->phys_cell_id = *scc->physCellId; - prach_pdu->num_prach_ocas = N_t_slot; - prach_pdu->prach_start_symbol = start_symbol; - prach_pdu->num_ra = fdm_index; - prach_pdu->num_cs = get_NCS(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig, - format0, - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig); - - LOG_D(MAC, "Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n", - frameP, slotP, - prach_occasion_id, prach_pdu->num_ra, - prach_pdu->prach_start_symbol, - slot_index, RA_sfn_index); - // SCF PRACH PDU format field does not consider A1/B1 etc. possibilities - // We added 9 = A1/B1 10 = A2/B2 11 A3/B3 - if (format1!=0xff) { - switch(format0) { - case 0xa1: - prach_pdu->prach_format = 11; - break; - case 0xa2: - prach_pdu->prach_format = 12; - break; - case 0xa3: - prach_pdu->prach_format = 13; - break; - default: - AssertFatal(1==0,"Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); + 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)); + UL_tti_req->n_pdus+=1; + + // filling the prach fapi structure + prach_pdu->phys_cell_id = *scc->physCellId; + prach_pdu->num_prach_ocas = N_t_slot; + prach_pdu->prach_start_symbol = start_symbol; + prach_pdu->num_ra = fdm_index; + prach_pdu->num_cs = get_NCS(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig, + format0, + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig); + + LOG_D(MAC, "Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n", + frameP, slotP, + prach_occasion_id, prach_pdu->num_ra, + prach_pdu->prach_start_symbol, + slot_index, RA_sfn_index); + // SCF PRACH PDU format field does not consider A1/B1 etc. possibilities + // We added 9 = A1/B1 10 = A2/B2 11 A3/B3 + if (format1!=0xff) { + switch(format0) { + case 0xa1: + prach_pdu->prach_format = 11; + break; + case 0xa2: + prach_pdu->prach_format = 12; + break; + case 0xa3: + prach_pdu->prach_format = 13; + break; + default: + AssertFatal(1==0,"Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); + } + } + else{ + switch(format0) { + case 0: + prach_pdu->prach_format = 0; + break; + case 1: + prach_pdu->prach_format = 1; + break; + case 2: + prach_pdu->prach_format = 2; + break; + case 3: + prach_pdu->prach_format = 3; + break; + case 0xa1: + prach_pdu->prach_format = 4; + break; + case 0xa2: + prach_pdu->prach_format = 5; + break; + case 0xa3: + prach_pdu->prach_format = 6; + break; + case 0xb1: + prach_pdu->prach_format = 7; + break; + case 0xb4: + prach_pdu->prach_format = 8; + break; + case 0xc0: + prach_pdu->prach_format = 9; + break; + case 0xc2: + prach_pdu->prach_format = 10; + break; + default: + AssertFatal(1==0,"Invalid PRACH format"); + } + } + } } } - else{ - switch(format0) { - case 0: - prach_pdu->prach_format = 0; - break; - case 1: - prach_pdu->prach_format = 1; - break; - case 2: - prach_pdu->prach_format = 2; - break; - case 3: - prach_pdu->prach_format = 3; - break; - case 0xa1: - prach_pdu->prach_format = 4; - break; - case 0xa2: - prach_pdu->prach_format = 5; - break; - case 0xa3: - prach_pdu->prach_format = 6; - break; - case 0xb1: - prach_pdu->prach_format = 7; - break; - case 0xb4: - prach_pdu->prach_format = 8; - break; - case 0xc0: - prach_pdu->prach_format = 9; - break; - case 0xc2: - prach_pdu->prach_format = 10; - break; - default: - AssertFatal(1==0,"Invalid PRACH format"); - } - } - } } - } - } } } @@ -363,7 +370,14 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu]; *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot *msg2_frame = (*msg2_slot>(rach_slot))? rach_frame : (rach_frame +1); - + + // we can't schedule msg2 before sl_ahead since prach + int eff_slot = *msg2_slot+(*msg2_frame-rach_frame)*nr_slots_per_frame[mu]; + if ((eff_slot-rach_slot)<=sl_ahead) { + *msg2_slot = (*msg2_slot+tdd_period_slot)%nr_slots_per_frame[mu]; + *msg2_frame = (*msg2_slot>(rach_slot))? rach_frame : (rach_frame +1); + } + switch(response_window){ case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: slot_window = 1; @@ -396,12 +410,11 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, // slot and frame limit to transmit msg2 according to response window uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu]; - //uint8_t frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1); - + uint8_t frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1); // go to previous slot if the current scheduled slot is beyond the response window // and if the slot is not among the PDCCH monitored ones (38.213 10.1) - while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) { + while (((*msg2_slot>slot_limit)&&(*msg2_frame>frame_limit)) || ((*msg2_frame*nr_slots_per_frame[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) { if((*msg2_slot%tdd_period_slot) > 0) (*msg2_slot)--; else @@ -562,7 +575,9 @@ void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){ stop_meas(&mac->schedule_ra); } -void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc, +void nr_get_Msg3alloc(module_id_t module_id, + int CC_id, + NR_ServingCellConfigCommon_t *scc, NR_BWP_Uplink_t *ubwp, sub_frame_t current_slot, frame_t current_frame, @@ -596,27 +611,25 @@ void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc, ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame[mu]); LOG_I(MAC, "[RAPROC] Msg3 slot %d: current slot %u Msg3 frame %u k2 %u Msg3_tda_id %u start symbol index %u\n", ra->Msg3_slot, current_slot, ra->Msg3_frame, k2,ra->Msg3_tda_id, StartSymbolIndex); - ra->msg3_nb_rb = 18; - ra->msg3_first_rb = 0; -} - - -void nr_schedule_reception_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP){ - gNB_MAC_INST *mac = RC.nrmac[module_idP]; - nfapi_nr_ul_tti_request_t *ul_req = &mac->UL_tti_req[0]; - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - NR_RA_t *ra = &cc->ra[0]; - - if (ra->state == WAIT_Msg3) { - if ((frameP == ra->Msg3_frame) && (slotP == ra->Msg3_slot) ){ - ul_req->SFN = ra->Msg3_frame; - ul_req->Slot = ra->Msg3_slot; - ul_req->pdus_list[ul_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; - ul_req->pdus_list[ul_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - ul_req->pdus_list[ul_req->n_pdus].pusch_pdu = ra->pusch_pdu; - ul_req->n_pdus+=1; - } + uint16_t *vrb_map_UL = + &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * 275]; + const uint16_t bwpSize = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275); + /* search 18 free RBs */ + int rbSize = 0; + int rbStart = 0; + while (rbSize < 18) { + rbStart += rbSize; /* last iteration rbSize was not enough, skip it */ + rbSize = 0; + while (rbStart < bwpSize && vrb_map_UL[rbStart]) + rbStart++; + AssertFatal(rbStart < bwpSize - 18, "no space to allocate Msg 3 for RA!\n"); + while (rbStart + rbSize < bwpSize + && !vrb_map_UL[rbStart + rbSize] + && rbSize < 18) + rbSize++; } + ra->msg3_nb_rb = 18; + ra->msg3_first_rb = rbStart; } void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP){ @@ -631,10 +644,32 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t return; } + uint16_t *vrb_map_UL = + &RC.nrmac[module_idP]->common_channels[CC_id].vrb_map_UL[ra->Msg3_slot * 275]; + for (int i = 0; i < ra->msg3_nb_rb; ++i) { + AssertFatal(!vrb_map_UL[i + ra->msg3_first_rb], + "RB %d in %4d.%2d is already taken, cannot allocate Msg3!\n", + i + ra->msg3_first_rb, + ra->Msg3_frame, + ra->Msg3_slot); + vrb_map_UL[i + ra->msg3_first_rb] = 1; + } + LOG_I(MAC, "[gNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot); - nfapi_nr_pusch_pdu_t *pusch_pdu = &ra->pusch_pdu; + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][ra->Msg3_slot]; + 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", + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + ra->Msg3_frame, + ra->Msg3_slot); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); + future_ul_tti_req->n_pdus += 1; AssertFatal(ra->secondaryCellGroup, "no secondaryCellGroup for RNTI %04x\n", @@ -913,7 +948,7 @@ void nr_generate_Msg2(module_id_t module_idP, dl_req->nPDUs+=2; // Program UL processing for Msg3 - nr_get_Msg3alloc(scc, ubwp, slotP, frameP, ra); + nr_get_Msg3alloc(module_idP, CC_id, scc, ubwp, slotP, frameP, ra); LOG_I(MAC, "Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); nr_add_msg3(module_idP, CC_id, frameP, slotP); ra->state = WAIT_Msg3; @@ -990,7 +1025,7 @@ void nr_fill_rar(uint8_t Mod_idP, uint8_t * dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu){ - LOG_I(MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index); + LOG_I(MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u\n", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index); NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); unsigned char csi_req = 0, tpc_command; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 7a7fe1288c..429d88734b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -38,7 +38,6 @@ #include "NR_MAC_COMMON/nr_mac.h" #include "NR_MAC_gNB/nr_mac_gNB.h" #include "NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac.h" #include "LAYER2/NR_MAC_gNB/mac_proto.h" /*NFAPI*/ @@ -304,9 +303,8 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, // 2) Generation of DLSCH MAC subPDUs including subheaders and MAC SDUs for (i = 0; i < num_sdus; i++) { - LOG_D(MAC, "[gNB] Generate DLSCH header num sdu %d len sdu %d\n", num_sdus, sdu_lengths[i]); - if (sdu_lengths[i] < 128) { + if (sdu_lengths[i] < 256) { ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0; ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0; ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = sdu_lcids[i]; @@ -316,7 +314,7 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->R = 0; ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->F = 1; ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->LCID = sdu_lcids[i]; - ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0x7f; + ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0xff; ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L2 = (unsigned short) sdu_lengths[i] & 0xff; last_size = 3; } @@ -326,6 +324,7 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, memcpy((void *) mac_pdu_ptr, (void *) dlsch_buffer_ptr, sdu_lengths[i]); dlsch_buffer_ptr += sdu_lengths[i]; mac_pdu_ptr += sdu_lengths[i]; + LOG_D(MAC, "Generate DLSCH header num sdu %d len header %d len sdu %d -> offset %ld\n", num_sdus, last_size, sdu_lengths[i], (unsigned char *)mac_pdu_ptr - mac_pdu); } // 4) Compute final offset for padding @@ -333,6 +332,7 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->R = 0; ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->LCID = DL_SCH_LCID_PADDING; mac_pdu_ptr++; + LOG_D(MAC, "Generate Padding -> offset %ld\n", (unsigned char *)mac_pdu_ptr - mac_pdu); } else { // no MAC subPDU with padding } @@ -343,100 +343,6 @@ int nr_generate_dlsch_pdu(module_id_t module_idP, return offset; } -void nr_rx_acknack(nfapi_nr_uci_pusch_pdu_t *uci_pusch, - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01, - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234, - NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats) { - - // TODO - int max_harq_rounds = 4; // TODO define macro - - if (uci_01 != NULL) { - // handle harq - int harq_idx_s = 0; - - // iterate over received harq bits - for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { - // search for the right harq process - for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) { - // if the gNB received ack with a good confidence - if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { - if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) && - (uci_01->harq->harq_confidence_level == 0)) { - // toggle NDI and reset round - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - else - sched_ctrl->harq_processes[harq_idx].round++; - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - harq_idx_s = harq_idx + 1; - // if the max harq rounds was reached - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - stats->dlsch_errors++; - } - break; - } - // if feedback slot processing is aborted - else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) && - (sched_ctrl->harq_processes[harq_idx].is_waiting)) { - sched_ctrl->harq_processes[harq_idx].round++; - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - } - } - } - } - - - if (uci_234 != NULL) { - int harq_idx_s = 0; - int acknack; - - // iterate over received harq bits - for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { - acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01; - for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) { - // if the gNB received ack with a good confidence or if the max harq rounds was reached - if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { - // TODO add some confidence level for when there is no CRC - if ((uci_234->harq.harq_crc != 1) && acknack) { - // toggle NDI and reset round - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - else - sched_ctrl->harq_processes[harq_idx].round++; - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - harq_idx_s = harq_idx + 1; - // if the max harq rounds was reached - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - stats->dlsch_errors++; - } - break; - } - // if feedback slot processing is aborted - else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) && - (sched_ctrl->harq_processes[harq_idx].is_waiting)) { - sched_ctrl->harq_processes[harq_idx].round++; - if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { - sched_ctrl->harq_processes[harq_idx].ndi ^= 1; - sched_ctrl->harq_processes[harq_idx].round = 0; - } - sched_ctrl->harq_processes[harq_idx].is_waiting = 0; - } - } - } - } -} - int getNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda) { struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; @@ -487,7 +393,7 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id, /* Retrieve amount of data to send for this UE */ sched_ctrl->num_total_bytes = 0; const int lcid = DL_SCH_LCID_DTCH; - const uint16_t rnti = UE_info->rnti[UE_id]; + const rnti_t rnti = UE_info->rnti[UE_id]; sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id, rnti, module_id, @@ -502,12 +408,14 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id, if (sched_ctrl->num_total_bytes == 0 && !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */ return; - LOG_D(MAC, - "%d.%d, DTCH%d->DLSCH, RLC status %d bytes\n", + + LOG_D(MAC, "[%s][%d.%d], DTCH%d->DLSCH, RLC status %d bytes TA %d\n", + __FUNCTION__, frame, slot, lcid, - sched_ctrl->rlc_status[lcid].bytes_in_buffer); + sched_ctrl->rlc_status[lcid].bytes_in_buffer, + sched_ctrl->ta_apply); /* Find a free CCE */ const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; @@ -546,7 +454,8 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id, AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n"); uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map; - const int current_harq_pid = sched_ctrl->current_harq_pid; + // for now HARQ PID is fixed and should be the same as in post-processor + const int current_harq_pid = slot % num_slots_per_tdd; NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid]; const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275); @@ -598,6 +507,8 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id, sched_ctrl->time_domain_allocation); int rbSize = 0; + const int oh = 2 + (sched_ctrl->num_total_bytes >= 256) + + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024); uint32_t TBS = 0; do { rbSize++; @@ -611,7 +522,7 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id, 0 /* tb_scaling */, 1 /* nrOfLayers */) >> 3; - } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < sched_ctrl->num_total_bytes); + } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < sched_ctrl->num_total_bytes + oh); sched_ctrl->rbSize = rbSize; sched_ctrl->rbStart = rbStart; } @@ -641,8 +552,10 @@ void nr_schedule_ue_spec(module_id_t module_id, * 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 + 10) % 1024) - sched_ctrl->ta_apply = false; /* the timer is reset once TA CE is scheduled */ + if (frame == (sched_ctrl->ta_frame + 10) % 1024){ + sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */ + LOG_D(MAC, "[UE %d][%d.%d] UL timing alignment procedures: setting flag for Timing Advance command\n", UE_id, frame, slot); + } if (sched_ctrl->rbSize <= 0) continue; @@ -676,13 +589,17 @@ void nr_schedule_ue_spec(module_id_t module_id, 1 /* nrOfLayers */) >> 3; - const int current_harq_pid = sched_ctrl->current_harq_pid; + const int current_harq_pid = slot % num_slots_per_tdd; NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; NR_sched_pucch *pucch = &sched_ctrl->sched_pucch[sched_ctrl->pucch_sched_idx][sched_ctrl->pucch_occ_idx]; harq->feedback_slot = pucch->ul_slot; harq->is_waiting = 1; UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++; + LOG_D(MAC, "%4d.%2d RNTI %04x start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n", + frame, slot, rnti, sched_ctrl->rbStart, sched_ctrl->rbSize, sched_ctrl->mcs, + TBS, current_harq_pid, harq->round, harq->ndi); + nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; nr_fill_nfapi_dl_pdu(module_id, dl_req, @@ -725,9 +642,18 @@ void nr_schedule_ue_spec(module_id_t module_id, retInfo->numDmrsCdmGrpsNoData); /* we do not have to do anything, since we do not require to get data * from RLC, encode MAC CEs, or copy data to FAPI structures */ - LOG_W(MAC, "%d.%2d retransmission UE %d/RNTI %04x\n", frame, slot, UE_id, rnti); + LOG_W(MAC, + "%d.%2d DL retransmission UE %d/RNTI %04x HARQ PID %d round %d NDI %d\n", + frame, + slot, + UE_id, + rnti, + current_harq_pid, + harq->round, + harq->ndi); } else { /* initial transmission */ + LOG_D(MAC, "[%s] Initial HARQ transmission in %d.%d\n", __FUNCTION__, frame, slot); /* reserve space for timing advance of UE if necessary, * nr_generate_dlsch_pdu() checks for ta_apply and add TA CE if necessary */ const int ta_len = (sched_ctrl->ta_apply) ? 2 : 0; @@ -742,12 +668,17 @@ void nr_schedule_ue_spec(module_id_t module_id, unsigned char sdu_lcids[NB_RB_MAX] = {0}; const int lcid = DL_SCH_LCID_DTCH; if (sched_ctrl->num_total_bytes > 0) { + /* this is the data from the RLC we would like to request (e.g., only + * some bytes for first LC and some more from a second one */ + const rlc_buffer_occupancy_t ndata = sched_ctrl->rlc_status[lcid].bytes_in_buffer; + /* this is the maximum data we can transport based on TBS minus headers */ + const int mindata = min(ndata, TBS - ta_len - header_length_total - sdu_length_total - 2 - (ndata >= 256)); LOG_D(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting " "%d bytes from RLC (lcid %d total hdr len %d), TBS: %d \n \n", module_id, frame, - TBS - ta_len - header_length_total - sdu_length_total - 3, + mindata, lcid, header_length_total, TBS); @@ -759,7 +690,7 @@ void nr_schedule_ue_spec(module_id_t module_id, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS - ta_len - header_length_total - sdu_length_total - 3, + mindata, (char *)&mac_sdus[sdu_length_total], 0, 0); @@ -776,14 +707,14 @@ void nr_schedule_ue_spec(module_id_t module_id, header_length_total += header_length_last; num_sdus++; } - else if (get_softmodem_params()->phy_test) { + else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) { LOG_D(MAC, "Configuring DL_TX in %d.%d: random data\n", frame, slot); // fill dlsch_buffer with random data for (int i = 0; i < TBS; i++) mac_sdus[i] = (unsigned char) (lrand48()&0xff); sdu_lcids[0] = 0x3f; // DRB sdu_lengths[0] = TBS - ta_len - 3; - header_length_total += 2 + (sdu_lengths[0] >= 128); + header_length_total += 2 + (sdu_lengths[0] >= 256); sdu_length_total += sdu_lengths[0]; num_sdus +=1; } @@ -791,7 +722,7 @@ void nr_schedule_ue_spec(module_id_t module_id, UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS; UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += sdu_length_total; - const int post_padding = TBS >= 2 + header_length_total + sdu_length_total + ta_len; + const int post_padding = TBS > header_length_total + sdu_length_total + ta_len; const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs; nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index e14afacf09..0d6969ad5f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -258,8 +258,6 @@ void nr_preprocessor_phytest(module_id_t module_id, sub_frame_t slot, int num_slots_per_tdd) { - if (slot != 1) - return; /* only schedule in slot 1 for now */ NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; const int UE_id = 0; const int CC_id = 0; @@ -267,7 +265,6 @@ void nr_preprocessor_phytest(module_id_t module_id, "%s(): expected UE %d to be active\n", __func__, UE_id); - NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; /* find largest unallocated chunk */ const int bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275); @@ -317,7 +314,7 @@ void nr_preprocessor_phytest(module_id_t module_id, sched_ctrl->coreset = get_coreset( sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */); const int cid = sched_ctrl->coreset->controlResourceSetId; - const uint16_t Y = UE_info->Y[UE_id][cid][RC.nrmac[module_id]->current_slot]; + const uint16_t Y = UE_info->Y[UE_id][cid][slot]; const int m = UE_info->num_pdcch_cand[UE_id][cid]; sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], sched_ctrl->active_bwp, @@ -343,7 +340,14 @@ void nr_preprocessor_phytest(module_id_t module_id, sched_ctrl->rbStart = rbStart; sched_ctrl->rbSize = rbSize; sched_ctrl->time_domain_allocation = 2; - sched_ctrl->mcsTableIdx = 0; + if (!UE_info->secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table) + sched_ctrl->mcsTableIdx = 0; + else { + if (*UE_info->secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table == 0) + sched_ctrl->mcsTableIdx = 1; + else + sched_ctrl->mcsTableIdx = 2; + } sched_ctrl->mcs = 9; sched_ctrl->numDmrsCdmGrpsNoData = 1; @@ -352,457 +356,131 @@ void nr_preprocessor_phytest(module_id_t module_id, vrb_map[rb + sched_ctrl->rbStart] = 1; } -void config_uldci(NR_BWP_Uplink_t *ubwp, - nfapi_nr_pusch_pdu_t *pusch_pdu, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, - dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, int *rnti_types, - int time_domain_assignment, uint8_t tpc, - int n_ubwp, int bwp_id) { +void nr_ul_preprocessor_phytest(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + int num_slots_per_tdd, + uint64_t ulsch_in_slot_bitmap) { + gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + NR_COMMON_channels_t *cc = nr_mac->common_channels; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + NR_UE_info_t *UE_info = &nr_mac->UE_info; - switch(dci_formats[(pdcch_pdu_rel15->numDlDci)-1]) { - case NR_UL_DCI_FORMAT_0_0: - dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, - pusch_pdu->rb_start, - NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); + AssertFatal(UE_info->num_UEs <= 1, + "%s() cannot handle more than one UE, but found %d\n", + __func__, + UE_info->num_UEs); + if (UE_info->num_UEs == 0) + return; - dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; - dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; - dci_pdu_rel15->mcs = 9; + const int UE_id = 0; + const int CC_id = 0; - dci_pdu_rel15->format_indicator = 0; - dci_pdu_rel15->ndi = 1; - dci_pdu_rel15->rv = 0; - dci_pdu_rel15->harq_pid = 0; - dci_pdu_rel15->tpc = 1; - break; - case NR_UL_DCI_FORMAT_0_1: - dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; - dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; - dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; - dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; - dci_pdu_rel15->dai[0].val = 0; //TODO - // bwp indicator - if (n_ubwp < 4) - dci_pdu_rel15->bwp_indicator.val = bwp_id; - else - dci_pdu_rel15->bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 - // frequency domain assignment - if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) - dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, - pusch_pdu->rb_start, - NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); - else - AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); - // time domain assignment - dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; - // mcs - dci_pdu_rel15->mcs = pusch_pdu->mcs_index; - // tpc command for pusch - dci_pdu_rel15->tpc = tpc; - // SRS resource indicator - if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig != NULL) { - if (*ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook) - dci_pdu_rel15->srs_resource_indicator.val = 0; // taking resource 0 for SRS - else - AssertFatal(1==0,"Non Codebook configuration non supported\n"); - } - // Antenna Ports - dci_pdu_rel15->antenna_ports.val = 0; // TODO for now it is hardcoded, it should depends on cdm group no data and rank - // DMRS sequence initialization - dci_pdu_rel15->dmrs_sequence_initialization.val = pusch_pdu->scid; - break; - default : - AssertFatal(1==0,"Valid UL formats are 0_0 and 0_1 \n"); - } + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - LOG_D(MAC, "[gNB scheduler phytest] ULDCI type 0 payload: PDCCH CCEIndex %d, freq_alloc %d, time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n", - pdcch_pdu_rel15->dci_pdu.CceIndex[pdcch_pdu_rel15->numDlDci], - dci_pdu_rel15->frequency_domain_assignment.val, - dci_pdu_rel15->time_domain_assignment.val, - dci_pdu_rel15->frequency_hopping_flag.val, - dci_pdu_rel15->mcs, - dci_pdu_rel15->tpc, - dci_pdu_rel15->ndi, - dci_pdu_rel15->rv); - -} - -int8_t select_ul_harq_pid(NR_UE_sched_ctrl_t *sched_ctrl) { - - uint8_t hrq_id; - uint8_t max_ul_harq_pids = 3; // temp: for testing - // schedule active harq processes - NR_UE_ul_harq_t cur_harq; - for (hrq_id=0; hrq_id < max_ul_harq_pids; hrq_id++) { - cur_harq = sched_ctrl->ul_harq_processes[hrq_id]; - if (cur_harq.state==ACTIVE_NOT_SCHED) { -#ifdef UL_HARQ_PRINT - printf("[SCHED] Found ulharq id %d, scheduling it for retransmission\n",hrq_id); -#endif - return hrq_id; - } - } - - // schedule new harq processes - for (hrq_id=0; hrq_id < max_ul_harq_pids; hrq_id++) { - cur_harq = sched_ctrl->ul_harq_processes[hrq_id]; - if (cur_harq.state==INACTIVE) { -#ifdef UL_HARQ_PRINT - printf("[SCHED] Found new ulharq id %d, scheduling it\n",hrq_id); -#endif - return hrq_id; - } - } - LOG_E(MAC,"All UL HARQ processes are busy. Cannot schedule ULSCH\n"); - return -1; -} - -long get_K2(NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) { - DevAssert(ubwp); - const NR_PUSCH_TimeDomainResourceAllocation_t *tda_list = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]; - if (tda_list->k2) - return *tda_list->k2; - else if (mu < 2) - return 1; - else if (mu == 2) - return 2; - else - return 3; -} - -void schedule_fapi_ul_pdu(int Mod_idP, - frame_t frameP, - sub_frame_t slotP, - int num_slots_per_tdd, - int ul_slots, - int time_domain_assignment, - uint64_t ulsch_in_slot_bitmap) { - - gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP]; - NR_COMMON_channels_t *cc = nr_mac->common_channels; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - - int bwp_id=1; - int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; - int UE_id = 0; - NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id); - - NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; - AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, - "downlinkBWP_ToAddModList has %d BWP!\n", - secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; - int n_ubwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; - NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; - NR_PUSCH_Config_t *pusch_Config = ubwp->bwp_Dedicated->pusch_Config->choice.setup; - - AssertFatal(time_domain_assignmentbwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count, - "time_domain_assignment %d>=%d\n",time_domain_assignment,ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count); - - int K2 = get_K2(ubwp, time_domain_assignment,mu); - /* check if slot is UL, and for phy test verify that it is in first TDD - * period, slot 8 (for K2=2, this is at slot 6 in the gNB; because of UE + const int tda = 1; + const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = + sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + AssertFatal(tda < tdaList->list.count, + "time domain assignment %d >= %d\n", + tda, + tdaList->list.count); + int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu); + const int sched_frame = frame + (slot + K2 >= num_slots_per_tdd); + const int sched_slot = (slot + K2) % num_slots_per_tdd; + /* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE * limitations). Note that if K2 or the TDD configuration is changed, below * conditions might exclude each other and never be true */ - const int slot_idx = (slotP + K2) % num_slots_per_tdd; - if (is_xlsch_in_slot(ulsch_in_slot_bitmap, slot_idx) - && (!get_softmodem_params()->phy_test || slot_idx == 8)) { + if (!(is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot) && sched_slot == 8)) + return; - nfapi_nr_ul_dci_request_t *UL_dci_req = &RC.nrmac[Mod_idP]->UL_dci_req[0]; - UL_dci_req->SFN = frameP; - UL_dci_req->Slot = slotP; - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu; - - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, - "searchPsacesToAddModList is empty\n"); - - uint16_t rnti = UE_info->rnti[UE_id]; - - int first_ul_slot = num_slots_per_tdd - ul_slots; - NR_sched_pusch *pusch_sched = &UE_info->UE_sched_ctrl[UE_id].sched_pusch[slotP+K2-first_ul_slot]; - pusch_sched->frame = frameP; - pusch_sched->slot = slotP + K2; - pusch_sched->active = true; - nfapi_nr_pusch_pdu_t *pusch_pdu = &pusch_sched->pusch_pdu; - memset(pusch_pdu,0,sizeof(nfapi_nr_pusch_pdu_t)); - - LOG_D(MAC, "Scheduling UE specific PUSCH\n"); - //UL_tti_req = &nr_mac->UL_tti_req[CC_id]; - - int dci_formats[2]; - int rnti_types[2]; - - NR_SearchSpace_t *ss; - int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); - AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, - "searchPsacesToAddModList is empty\n"); - - int found=0; - - for (int i=0;ibwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) { - ss=bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i]; - AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n"); - AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n"); - if (ss->searchSpaceType->present == target_ss) { - found=1; - break; - } - } - AssertFatal(found==1,"Couldn't find an adequate searchspace\n"); - - if (ss->searchSpaceType->choice.ue_Specific->dci_Formats) - dci_formats[0] = NR_UL_DCI_FORMAT_0_1; - else - dci_formats[0] = NR_UL_DCI_FORMAT_0_0; - - rnti_types[0] = NR_RNTI_C; - - //Resource Allocation in time domain - int startSymbolAndLength=0; - int StartSymbolIndex,NrOfSymbols,mapping_type; - - startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; - SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols); - pusch_pdu->start_symbol_index = StartSymbolIndex; - pusch_pdu->nr_of_symbols = NrOfSymbols; - - mapping_type = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->mappingType; - - pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_pdu->rnti = rnti; - pusch_pdu->handle = 0; //not yet used - - pusch_pdu->bwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pusch_pdu->bwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); - pusch_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing; - pusch_pdu->cyclic_prefix = 0; - - if (pusch_Config->transformPrecoder == NULL) { - if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) - pusch_pdu->transform_precoding = 1; - else - pusch_pdu->transform_precoding = 0; - } - else - pusch_pdu->transform_precoding = *pusch_Config->transformPrecoder; - if (pusch_Config->dataScramblingIdentityPUSCH != NULL) - pusch_pdu->data_scrambling_id = *pusch_Config->dataScramblingIdentityPUSCH; - else - pusch_pdu->data_scrambling_id = *scc->physCellId; - - pusch_pdu->mcs_index = 9; - if (pusch_pdu->transform_precoding) - pusch_pdu->mcs_table = get_pusch_mcs_table(pusch_Config->mcs_Table, 0, - dci_formats[0], rnti_types[0], target_ss, false); - else - pusch_pdu->mcs_table = get_pusch_mcs_table(pusch_Config->mcs_TableTransformPrecoder, 1, - dci_formats[0], rnti_types[0], target_ss, false); - - pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table); - pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table); - if (pusch_Config->tp_pi2BPSK!=NULL) { - if(((pusch_pdu->mcs_table==3)&&(pusch_pdu->mcs_index<2)) || - ((pusch_pdu->mcs_table==4)&&(pusch_pdu->mcs_index<6))) { - pusch_pdu->target_code_rate = pusch_pdu->target_code_rate>>1; - pusch_pdu->qam_mod_order = pusch_pdu->qam_mod_order<<1; - } - } - pusch_pdu->nrOfLayers = 1; - - //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] - if (pusch_Config->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) { - pusch_pdu->resource_alloc = 1; //type 1 - pusch_pdu->rb_start = 0; - if (get_softmodem_params()->phy_test==1) - pusch_pdu->rb_size = min(pusch_pdu->bwp_size,50); - else - pusch_pdu->rb_size = pusch_pdu->bwp_size; - } - else - AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); - - pusch_pdu->vrb_to_prb_mapping = 0; - - if (pusch_Config->frequencyHopping==NULL) - pusch_pdu->frequency_hopping = 0; - else - pusch_pdu->frequency_hopping = 1; - - //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] - //pusch_pdu->uplink_frequency_shift_7p5khz = 0; - - - // -------------------- - // ------- DMRS ------- - // -------------------- - NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig; - if (mapping_type == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA) - NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; - else - NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; - if (NR_DMRS_UplinkConfig->dmrs_Type == NULL) - pusch_pdu->dmrs_config_type = 0; - else - pusch_pdu->dmrs_config_type = 1; - pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] - if (pusch_pdu->transform_precoding) { // transform precoding disabled - long *scramblingid; - if (pusch_pdu->scid == 0) - scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; - else - scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; - if (scramblingid == NULL) - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; - else - pusch_pdu->ul_dmrs_scrambling_id = *scramblingid; - } - else { - pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; - if (NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) - pusch_pdu->pusch_identity = *NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; - else - pusch_pdu->pusch_identity = *scc->physCellId; - } - pusch_dmrs_AdditionalPosition_t additional_pos; - if (NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL) - additional_pos = 2; - else { - if (*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3) - additional_pos = 3; - else - additional_pos = *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition; - } - pusch_maxLength_t pusch_maxLength; - if (NR_DMRS_UplinkConfig->maxLength == NULL) - pusch_maxLength = 1; - else - pusch_maxLength = 2; - uint16_t l_prime_mask = get_l_prime(pusch_pdu->nr_of_symbols, mapping_type, additional_pos, pusch_maxLength); - pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << pusch_pdu->start_symbol_index; - - pusch_pdu->num_dmrs_cdm_grps_no_data = 1; - pusch_pdu->dmrs_ports = 1; - // -------------------------------------------------------------------------------------------------------------------------------------------- - - // -------------------- - // ------- PTRS ------- - // -------------------- - if (NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { - // TODO to be fixed from RRC config - uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig - pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); - pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); - pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - - pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS - } - else{ - pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS - } - - // -------------------------------------------------------------------------------------------------------------------------------------------- - - //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] - //Optional Data only included if indicated in pduBitmap - int8_t harq_id = select_ul_harq_pid(&UE_info->UE_sched_ctrl[UE_id]); - if (harq_id < 0) return; - NR_UE_ul_harq_t *cur_harq = &UE_info->UE_sched_ctrl[UE_id].ul_harq_processes[harq_id]; - pusch_pdu->pusch_data.harq_process_id = harq_id; - pusch_pdu->pusch_data.new_data_indicator = cur_harq->ndi; - pusch_pdu->pusch_data.rv_index = nr_rv_round_map[cur_harq->round]; - - cur_harq->state = ACTIVE_SCHED; - cur_harq->last_tx_slot = pusch_sched->slot; - - uint8_t num_dmrs_symb = 0; - - for(int dmrs_counter = pusch_pdu->start_symbol_index; dmrs_counter < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; dmrs_counter++) - num_dmrs_symb += ((pusch_pdu->ul_dmrs_symb_pos >> dmrs_counter) & 1); - - uint8_t N_PRB_DMRS; - if (pusch_pdu->dmrs_config_type == 0) { - N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*6; - } - else { - N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*4; - } - - pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order, - pusch_pdu->target_code_rate, - pusch_pdu->rb_size, - pusch_pdu->nr_of_symbols, - N_PRB_DMRS * num_dmrs_symb, - 0, //nb_rb_oh - 0, - pusch_pdu->nrOfLayers)>>3; - - UE_info->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++; - if (cur_harq->round == 0) UE_info->mac_stats[UE_id].ulsch_total_bytes_scheduled+=pusch_pdu->pusch_data.tb_size; - - pusch_pdu->pusch_data.num_cb = 0; //CBG not supported - //pusch_pdu->pusch_data.cb_present_and_position; - //pusch_pdu->pusch_uci; - //pusch_pdu->pusch_ptrs; - //pusch_pdu->dfts_ofdm; - //beamforming - //pusch_pdu->beamforming; //not used for now - - - ul_dci_request_pdu = &UL_dci_req->ul_dci_pdu_list[UL_dci_req->numPdus]; - memset((void*)ul_dci_request_pdu,0,sizeof(nfapi_nr_ul_dci_request_pdus_t)); - ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; - UL_dci_req->numPdus+=1; - - - LOG_D(MAC,"Configuring ULDCI/PDCCH in %d.%d\n", frameP,slotP); - - uint8_t nr_of_candidates, aggregation_level; - find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss); - NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 1 /* dedicated */); - const int cid = coreset->controlResourceSetId; - const uint16_t Y = UE_info->Y[UE_id][cid][nr_mac->current_slot]; - const int m = UE_info->num_pdcch_cand[UE_id][cid]; - int CCEIndex = allocate_nr_CCEs(nr_mac, - bwp, - coreset, - aggregation_level, - Y, - m, - nr_of_candidates); - if (CCEIndex < 0) { - LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__); - pusch_sched->active = false; + const uint16_t rbStart = 0; + const uint16_t rbSize = 50; /* due to OAI UE limitations */ + uint16_t *vrb_map_UL = + &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * 275]; + for (int i = rbStart; i < rbStart + rbSize; ++i) { + if (vrb_map_UL[i]) { + LOG_E(MAC, + "%s(): %4d.%2d RB %d is already reserved, cannot schedule UE\n", + __func__, + frame, + slot, + i); return; } - else { - UE_info->num_pdcch_cand[UE_id][cid]++; - nr_configure_pdcch(nr_mac, - pdcch_pdu_rel15, - UE_info->rnti[UE_id], - ss, - coreset, - scc, - bwp, - aggregation_level, - CCEIndex); - - dci_pdu_rel15_t *dci_pdu_rel15 = calloc(MAX_DCI_CORESET,sizeof(dci_pdu_rel15_t)); - config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15,&dci_pdu_rel15[0],dci_formats,rnti_types,time_domain_assignment,UE_info->UE_sched_ctrl[UE_id].tpc0,n_ubwp,bwp_id); - fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pusch_pdu->bwp_size,bwp_id); - free(dci_pdu_rel15); - } } -} + sched_ctrl->sched_pusch.slot = sched_slot; + sched_ctrl->sched_pusch.frame = sched_frame; + + const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss); + uint8_t nr_of_candidates; + find_aggregation_candidates(&sched_ctrl->aggregation_level, + &nr_of_candidates, + sched_ctrl->search_space); + sched_ctrl->coreset = get_coreset( + sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */); + const int cid = sched_ctrl->coreset->controlResourceSetId; + const uint16_t Y = UE_info->Y[UE_id][cid][slot]; + const int m = UE_info->num_pdcch_cand[UE_id][cid]; + sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], + sched_ctrl->active_bwp, + sched_ctrl->coreset, + sched_ctrl->aggregation_level, + Y, + m, + nr_of_candidates); + if (sched_ctrl->cce_index < 0) { + LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__); + return; + } + UE_info->num_pdcch_cand[UE_id][cid]++; + + sched_ctrl->sched_pusch.time_domain_allocation = tda; + const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; + const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0; + const uint8_t num_dmrs_cdm_grps_no_data = 1; + /* we want to avoid a lengthy deduction of DMRS and other parameters in + * every TTI if we can save it, so check whether dci_format, TDA, or + * num_dmrs_cdm_grps_no_data has changed and only then recompute */ + NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save; + if (ps->time_domain_allocation != tda + || ps->dci_format != dci_format + || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data) + nr_save_pusch_fields(scc, + sched_ctrl->active_ubwp, + dci_format, + tda, + num_dmrs_cdm_grps_no_data, + ps); + + const int mcs = 9; + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + sched_pusch->mcs = mcs; + sched_pusch->rbStart = rbStart; + sched_pusch->rbSize = rbSize; + + /* Calculate TBS from MCS */ + sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table); + sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table); + if (ps->pusch_Config->tp_pi2BPSK + && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) { + sched_pusch->R >>= 1; + sched_pusch->Qm <<= 1; + } + sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, + sched_pusch->R, + sched_pusch->rbSize, + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->num_dmrs_symb, + 0, // nb_rb_oh + 0, + 1 /* NrOfLayers */) + >> 3; + + /* mark the corresponding RBs as used */ + for (int rb = rbStart; rb < rbStart + rbSize; rb++) + vrb_map_UL[rb] = 1; +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index dda70ef66a..f3260ea3cf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -32,7 +32,6 @@ #include "assertions.h" -#include "LAYER2/MAC/mac.h" #include "NR_MAC_gNB/nr_mac_gNB.h" #include "NR_MAC_COMMON/nr_mac_extern.h" @@ -48,9 +47,6 @@ #include "RRC/NR/nr_rrc_extern.h" #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" -//#include "LAYER2/MAC/pre_processor.c" -#include "pdcp.h" - #include "intertask_interface.h" #include "T.h" @@ -213,6 +209,75 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac, } +void nr_save_pusch_fields(const NR_ServingCellConfigCommon_t *scc, + const NR_BWP_Uplink_t *ubwp, + long dci_format, + int tda, + uint8_t num_dmrs_cdm_grps_no_data, + NR_sched_pusch_save_t *ps) +{ + ps->dci_format = dci_format; + ps->time_domain_allocation = tda; + ps->num_dmrs_cdm_grps_no_data = num_dmrs_cdm_grps_no_data; + + const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = + ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength; + SLIV2SL(startSymbolAndLength, + &ps->startSymbolIndex, + &ps->nrOfSymbols); + + ps->pusch_Config = ubwp->bwp_Dedicated->pusch_Config->choice.setup; + if (!ps->pusch_Config->transformPrecoder) + ps->transform_precoding = !scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder; + else + ps->transform_precoding = *ps->pusch_Config->transformPrecoder; + const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + if (ps->transform_precoding) + ps->mcs_table = get_pusch_mcs_table(ps->pusch_Config->mcs_Table, + 0, + ps->dci_format, + NR_RNTI_C, + target_ss, + false); + else + ps->mcs_table = get_pusch_mcs_table(ps->pusch_Config->mcs_TableTransformPrecoder, + 1, + ps->dci_format, + NR_RNTI_C, + target_ss, + false); + + /* DMRS calculations */ + ps->mapping_type = tdaList->list.array[tda]->mappingType; + ps->NR_DMRS_UplinkConfig = + ps->mapping_type == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA + ? ps->pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup + : ps->pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + ps->dmrs_config_type = ps->NR_DMRS_UplinkConfig->dmrs_Type == NULL ? 0 : 1; + const pusch_dmrs_AdditionalPosition_t additional_pos = + ps->NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL + ? 2 + : (*ps->NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == + NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3 + ? 3 + : *ps->NR_DMRS_UplinkConfig->dmrs_AdditionalPosition); + const pusch_maxLength_t pusch_maxLength = + ps->NR_DMRS_UplinkConfig->maxLength == NULL ? 1 : 2; + const uint16_t l_prime_mask = get_l_prime(ps->nrOfSymbols, + ps->mapping_type, + additional_pos, + pusch_maxLength); + ps->ul_dmrs_symb_pos = l_prime_mask << ps->startSymbolIndex; + uint8_t num_dmrs_symb = 0; + for(int i = ps->startSymbolIndex; i < ps->startSymbolIndex + ps->nrOfSymbols; i++) + num_dmrs_symb += (ps->ul_dmrs_symb_pos >> i) & 1; + ps->num_dmrs_symb = num_dmrs_symb; + ps->N_PRB_DMRS = ps->dmrs_config_type == 0 + ? num_dmrs_cdm_grps_no_data * 6 + : num_dmrs_cdm_grps_no_data * 4; +} + void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, nr_scs_e scs_common, nr_scs_e pdcch_scs, @@ -453,6 +518,8 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP, const int bwp_id = sched_ctrl->active_bwp->bwp_Id; const int nrOfLayers = 1; const int mcs = sched_ctrl->mcs; + const int mcs_table_index = sched_ctrl->mcsTableIdx; + bool valid_ptrs_setup = false; AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList has %d BWP!\n", @@ -491,10 +558,10 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP, pdsch_pdu_rel15->CyclicPrefix = 0; pdsch_pdu_rel15->NrOfCodewords = 1; - pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcs,0); + pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcs, mcs_table_index); pdsch_pdu_rel15->qamModOrder[0] = 2; pdsch_pdu_rel15->mcsIndex[0] = mcs; - pdsch_pdu_rel15->mcsTable[0] = 0; + pdsch_pdu_rel15->mcsTable[0] = mcs_table_index; pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[round]; pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; pdsch_pdu_rel15->nrOfLayers = nrOfLayers; @@ -521,6 +588,19 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP, scc->dmrs_TypeA_Position, pdsch_pdu_rel15->NrOfSymbols); + /* Check and validate PTRS values */ + if(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) { + valid_ptrs_setup = set_dl_ptrs_values(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup, + pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->mcsIndex[0], + pdsch_pdu_rel15->mcsTable[0], + &pdsch_pdu_rel15->PTRSFreqDensity,&pdsch_pdu_rel15->PTRSTimeDensity, + &pdsch_pdu_rel15->PTRSPortIndex,&pdsch_pdu_rel15->nEpreRatioOfPDSCHToPTRS, + &pdsch_pdu_rel15->PTRSReOffset, pdsch_pdu_rel15->NrOfSymbols); + if(valid_ptrs_setup==true) { + pdsch_pdu_rel15->pduBitmap |=0x1; + } + } + dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15_t) * MAX_DCI_CORESET); @@ -623,6 +703,81 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP, dl_req->nPDUs += 2; } +void config_uldci(NR_BWP_Uplink_t *ubwp, + nfapi_nr_pusch_pdu_t *pusch_pdu, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + dci_pdu_rel15_t *dci_pdu_rel15, + int *dci_formats, + int time_domain_assignment, uint8_t tpc, + int n_ubwp, int bwp_id) { + const int bw = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275); + switch (dci_formats[(pdcch_pdu_rel15->numDlDci) - 1]) { + case NR_UL_DCI_FORMAT_0_0: + dci_pdu_rel15->frequency_domain_assignment.val = + PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw); + + dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; + dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; + dci_pdu_rel15->mcs = pusch_pdu->mcs_index; + + dci_pdu_rel15->format_indicator = 0; + dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; + dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; + dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; + dci_pdu_rel15->tpc = tpc; + break; + case NR_UL_DCI_FORMAT_0_1: + dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; + dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; + dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; + dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; + dci_pdu_rel15->dai[0].val = 0; //TODO + // bwp indicator + if (n_ubwp < 4) + dci_pdu_rel15->bwp_indicator.val = bwp_id; + else + dci_pdu_rel15->bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 + // frequency domain assignment + AssertFatal(ubwp->bwp_Dedicated->pusch_Config->choice.setup->resourceAllocation + == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1, + "Only frequency resource allocation type 1 is currently supported\n"); + dci_pdu_rel15->frequency_domain_assignment.val = + PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, bw); + // time domain assignment + dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; + // mcs + dci_pdu_rel15->mcs = pusch_pdu->mcs_index; + // tpc command for pusch + dci_pdu_rel15->tpc = tpc; + // SRS resource indicator + if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig != NULL) { + AssertFatal(*ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook, + "Non Codebook configuration non supported\n"); + dci_pdu_rel15->srs_resource_indicator.val = 0; // taking resource 0 for SRS + } + // Antenna Ports + dci_pdu_rel15->antenna_ports.val = 0; // TODO for now it is hardcoded, it should depends on cdm group no data and rank + // DMRS sequence initialization + dci_pdu_rel15->dmrs_sequence_initialization.val = pusch_pdu->scid; + break; + default : + AssertFatal(0, "Valid UL formats are 0_0 and 0_1\n"); + } + + LOG_D(MAC, + "%s() ULDCI type 0 payload: PDCCH CCEIndex %d, freq_alloc %d, " + "time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n", + __func__, + pdcch_pdu_rel15->dci_pdu.CceIndex[pdcch_pdu_rel15->numDlDci], + dci_pdu_rel15->frequency_domain_assignment.val, + dci_pdu_rel15->time_domain_assignment.val, + dci_pdu_rel15->frequency_hopping_flag.val, + dci_pdu_rel15->mcs, + dci_pdu_rel15->tpc, + dci_pdu_rel15->ndi, + dci_pdu_rel15->rv); +} + void nr_configure_pdcch(gNB_MAC_INST *nr_mac, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu, uint16_t rnti, @@ -919,84 +1074,6 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu, } -uint16_t compute_pucch_prb_size(uint8_t format, - uint8_t nr_prbs, - uint16_t O_tot, - uint16_t O_csi, - NR_PUCCH_MaxCodeRate_t *maxCodeRate, - uint8_t Qm, - uint8_t n_symb, - uint8_t n_re_ctrl) { - - uint16_t O_crc; - - if (O_tot<12) - O_crc = 0; - else{ - if (O_tot<20) - O_crc = 6; - else { - if (O_tot<360) - O_crc = 11; - else - AssertFatal(1==0,"Case for segmented PUCCH not yet implemented"); - } - } - - int rtimes100; - switch(*maxCodeRate){ - case NR_PUCCH_MaxCodeRate_zeroDot08 : - rtimes100 = 8; - break; - case NR_PUCCH_MaxCodeRate_zeroDot15 : - rtimes100 = 15; - break; - case NR_PUCCH_MaxCodeRate_zeroDot25 : - rtimes100 = 25; - break; - case NR_PUCCH_MaxCodeRate_zeroDot35 : - rtimes100 = 35; - break; - case NR_PUCCH_MaxCodeRate_zeroDot45 : - rtimes100 = 45; - break; - case NR_PUCCH_MaxCodeRate_zeroDot60 : - rtimes100 = 60; - break; - case NR_PUCCH_MaxCodeRate_zeroDot80 : - rtimes100 = 80; - break; - default : - AssertFatal(1==0,"Invalid MaxCodeRate"); - } - - float r = (float)rtimes100/100; - - if (O_csi == O_tot) { - if ((O_tot+O_csi)>(nr_prbs*n_re_ctrl*n_symb*Qm*r)) - AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs", - r,O_tot,O_crc,nr_prbs); - else - return nr_prbs; - } - - if (format==2){ - // TODO fix this for multiple CSI reports - for (int i=1; i<=nr_prbs; i++){ - if((O_tot+O_crc)<=(i*n_symb*Qm*n_re_ctrl*r) && - (O_tot+O_crc)>((i-1)*n_symb*Qm*n_re_ctrl*r)) - return i; - } - AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with at most %d PRBs", - r,O_tot,O_crc,nr_prbs); - } - else{ - AssertFatal(1==0,"Not yet implemented"); - } - -} - - void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu_rel15_t *dci_pdu_rel15, nr_dci_format_t format, @@ -1785,20 +1862,17 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){ UE_info->UE_sched_ctrl[UE_id].ta_update = 31; UE_info->UE_sched_ctrl[UE_id].ta_apply = false; UE_info->UE_sched_ctrl[UE_id].ul_rssi = 0; + /* set illegal time domain allocation to force recomputation of all fields */ + UE_info->UE_sched_ctrl[UE_id].pusch_save.time_domain_allocation = -1; UE_info->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch **)malloc(num_slots_ul*sizeof(NR_sched_pucch *)); for (int s=0; sUE_sched_ctrl[UE_id].sched_pucch[s] = (NR_sched_pucch *)malloc(2*sizeof(NR_sched_pucch)); - UE_info->UE_sched_ctrl[UE_id].sched_pusch = (NR_sched_pusch *)malloc(num_slots_ul*sizeof(NR_sched_pusch)); for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l], 0, sizeof(NR_sched_pucch)); - - memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pusch[k], - 0, - sizeof(NR_sched_pusch)); } LOG_I(MAC, "gNB %d] Add NR UE_id %d : rnti %x\n", mod_idP, @@ -1840,7 +1914,6 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti) UE_info->rnti[UE_id] = 0; remove_nr_ue_list(&UE_info->list, UE_id); free(UE_info->UE_sched_ctrl[UE_id].sched_pucch); - free(UE_info->UE_sched_ctrl[UE_id].sched_pusch); memset((void *) &UE_info->UE_sched_ctrl[UE_id], 0, sizeof(NR_UE_sched_ctrl_t)); @@ -1921,324 +1994,6 @@ void get_pdsch_to_harq_feedback(int Mod_idP, } -uint16_t nr_get_csi_bitlen(int Mod_idP, - int UE_id, - uint8_t csi_report_id) { - - uint16_t csi_bitlen =0; - NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - CRI_SSBRI_RSRP_bitlen_t * CSI_report_bitlen = NULL; - - CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0]); - csi_bitlen = ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) + - CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen * - (CSI_report_bitlen->nb_ssbri_cri -1 )) *UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report); - - return csi_bitlen; -} - - -void csi_period_offset(NR_CSI_ReportConfig_t *csirep, - int *period, int *offset) { - - NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present; - - switch(p_and_o){ - case NR_CSI_ReportPeriodicityAndOffset_PR_slots4: - *period = 4; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots5: - *period = 5; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots8: - *period = 8; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots10: - *period = 10; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots16: - *period = 16; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots20: - *period = 20; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots40: - *period = 40; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots80: - *period = 80; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots160: - *period = 160; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160; - break; - case NR_CSI_ReportPeriodicityAndOffset_PR_slots320: - *period = 320; - *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320; - break; - default: - AssertFatal(1==0,"No periodicity and offset resource found in CSI report"); - } -} - - -//!TODO : same function can be written to handle csi_resources -void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id) { - uint8_t csi_report_id = 0; - uint8_t csi_resourceidx =0; - uint8_t csi_ssb_idx =0; - - NR_CSI_MeasConfig_t *csi_MeasConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; - NR_CSI_ResourceConfigId_t csi_ResourceConfigId; - for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ - csi_ResourceConfigId=csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->resourcesForChannelMeasurement; - UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportQuantity.present; - - for ( csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { - if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_ResourceConfigId != csi_ResourceConfigId) - continue; - else { - //Finding the CSI_RS or SSB Resources - UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type= csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.present; - if (NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB ==UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type){ - struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList__nzp_CSI_RS_SSB * nzp_CSI_RS_SSB = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB; - - UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report = nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count:0; - UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = nzp_CSI_RS_SSB->csi_SSB_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count:0; - } - - if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report){ - uint8_t nb_ssb_resources =0; - for ( 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_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig - if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == - csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.present ) { - if (NULL != csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS) - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri = *(csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; - else - /*! From Spec 38.331 - * nrofReportedRS - * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE - * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report. - * When the field is absent the UE applies the value 1 - */ - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 1; - }else - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 2; - - nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; - if (nb_ssb_resources){ - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources)); - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP - } - else{ - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =0; - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 0; - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =0; - } - - LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d", - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen, - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen, - UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen); - break ; - } - } - } - if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report){ - AssertFatal(1==0,"Currently configuring only SSB beamreporting."); - } - break; - } - } - } -} - -void nr_csi_meas_reporting(int Mod_idP, - int UE_id, - frame_t frame, - sub_frame_t slot, - int slots_per_tdd, - int ul_slots, - int n_slots_frame) { - - NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - NR_sched_pucch *curr_pucch; - NR_PUCCH_ResourceSet_t *pucchresset; - NR_CSI_ReportConfig_t *csirep; - NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; - NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; - NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]; - NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup; - - AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count>0,"NO CSI report configuration available"); - - for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ - - csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; - - AssertFatal(csirep->reportConfigType.choice.periodic!=NULL,"Only periodic CSI reporting is implemented currently"); - int period, offset, sched_slot; - csi_period_offset(csirep,&period,&offset); - sched_slot = (period+offset)%n_slots_frame; - // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214 - // preparation is done in first slot of tdd period - if ( (frame%(period/n_slots_frame)==(offset/n_slots_frame)) && (slot==((sched_slot/slots_per_tdd)*slots_per_tdd))) { - - // we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack) - curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[sched_slot-slots_per_tdd+ul_slots][0]; - - NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; - - int found = -1; - pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 - int n_list = pucchresset->resourceList.list.count; - for (int i=0; iresourceList.list.array[i] == pucchcsires->pucch_Resource) - found = i; - } - AssertFatal(found>-1,"CSI resource not found among PUCCH resources"); - - curr_pucch->resource_indicator = found; - - n_list = pucch_Config->resourceToAddModList->list.count; - - // going through the list of PUCCH resources to find the one indexed by resource_id - for (int i=0; iresourceToAddModList->list.array[i]; - if (pucchres->pucch_ResourceId == *pucchresset->resourceList.list.array[found]) { - switch(pucchres->format.present){ - case NR_PUCCH_Resource__format_PR_format2: - if (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL) - curr_pucch->simultaneous_harqcsi = false; - else - curr_pucch->simultaneous_harqcsi = true; - break; - case NR_PUCCH_Resource__format_PR_format3: - if (pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI == NULL) - curr_pucch->simultaneous_harqcsi = false; - else - curr_pucch->simultaneous_harqcsi = true; - break; - case NR_PUCCH_Resource__format_PR_format4: - if (pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI == NULL) - curr_pucch->simultaneous_harqcsi = false; - else - curr_pucch->simultaneous_harqcsi = true; - break; - default: - AssertFatal(1==0,"Invalid PUCCH format type"); - } - } - } - curr_pucch->csi_bits += nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // TODO function to compute CSI meas report bit size - curr_pucch->frame = frame; - curr_pucch->ul_slot = sched_slot; - } - } -} - - -// function to update pucch scheduling parameters in UE list when a USS DL is scheduled -void nr_acknack_scheduling(int Mod_idP, - int UE_id, - frame_t frameP, - sub_frame_t slotP, - int slots_per_tdd, - int *pucch_id, - int *pucch_occ) { - - NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; - NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; - NR_sched_pucch *curr_pucch; - int max_acknacks,pucch_res,first_ul_slot_tdd,k,i,l; - uint8_t pdsch_to_harq_feedback[8]; - int found = 0; - int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) - nr_ulmix_slots++; - - bool csi_pres=false; - for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits>0) - csi_pres=true; - } - - // As a preference always schedule ack nacks in PUCCH0 (max 2 per slots) - // Unless there is CSI meas reporting scheduled in the period to avoid conflicts in the same slot - if (csi_pres) - max_acknacks=10; - else - max_acknacks=2; - - // this is hardcoded for now as ue specific - NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback); - - // for each possible ul or mixed slot - for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l]; - //if it is possible to schedule acknack in current pucch (no exclusive csi pucch) - if ((curr_pucch->csi_bits == 0) || (curr_pucch->simultaneous_harqcsi==true)) { - // if there is free room in current pucch structure - if (curr_pucch->dai_c-1){ - curr_pucch->resource_indicator = pucch_res; - curr_pucch->frame = frameP; - // first pucch occasion in first UL or MIXED slot - first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; - i = 0; - while (i<8 && found == 0) { // look if timing indicator is among allowed values - if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd)) - found = 1; - if (found == 0) i++; - } - if (found == 1) { - // computing slot in which pucch is scheduled - curr_pucch->dai_c++; - curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd)); - curr_pucch->timing_indicator = i; // index in the list of timing indicators - *pucch_id = k; - *pucch_occ = l; - return; - } - } - } - } - } - } - AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n"); -} - - -int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l) { - - // to be updated later, for now simple implementation - // use the second allocation just in case there is csi in the first - // in that case use second resource (for a different symbol) see 9.2 in 38.213 - if (l==1) { - if (UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits==0) - return -1; - else - return 1; - } - else - return 0; - -} - void find_aggregation_candidates(uint8_t *aggregation_level, uint8_t *nr_of_candidates, NR_SearchSpace_t *ss) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c new file mode 100644 index 0000000000..ec5195ec5b --- /dev/null +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -0,0 +1,628 @@ +/* + * 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 gNB_scheduler_uci.c + * \brief MAC procedures related to UCI + * \date 2020 + * \version 1.0 + * \company Eurecom + */ + +#include "LAYER2/MAC/mac.h" +#include "NR_MAC_gNB/nr_mac_gNB.h" +#include "NR_MAC_COMMON/nr_mac_extern.h" +#include "NR_MAC_gNB/mac_proto.h" +#include "common/ran_context.h" + +extern RAN_CONTEXT_t RC; + +void nr_schedule_pucch(int Mod_idP, + int UE_id, + int nr_ulmix_slots, + frame_t frameP, + sub_frame_t slotP) { + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id); + + for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l]; + const uint16_t O_ack = curr_pucch->dai_c; + const uint16_t O_csi = curr_pucch->csi_bits; + const uint8_t O_sr = 0; // no SR in PUCCH implemented for now + if (O_ack + O_csi + O_sr == 0 + || frameP != curr_pucch->frame + || slotP != curr_pucch->ul_slot) + continue; + + nfapi_nr_ul_tti_request_t *future_ul_tti_req = + &RC.nrmac[Mod_idP]->UL_tti_req_ahead[0][curr_pucch->ul_slot]; + AssertFatal(future_ul_tti_req->SFN == curr_pucch->frame + && future_ul_tti_req->Slot == curr_pucch->ul_slot, + "future UL_tti_req's frame.slot %d.%d does not match PUCCH %d.%d\n", + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + curr_pucch->frame, + curr_pucch->ul_slot); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t); + nfapi_nr_pucch_pdu_t *pucch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pucch_pdu; + memset(pucch_pdu, 0, sizeof(nfapi_nr_pucch_pdu_t)); + future_ul_tti_req->n_pdus += 1; + + LOG_D(MAC, + "%4d.%2d Scheduling pucch reception in %4d.%2d: bits SR %d, ACK %d, CSI %d, k %d l %d\n", + frameP, + slotP, + curr_pucch->frame, + curr_pucch->ul_slot, + O_sr, + O_ack, + O_csi, + k, l); + + NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; + nr_configure_pucch(pucch_pdu, + scc, + UE_info->UE_sched_ctrl[UE_id].active_ubwp, + UE_info->rnti[UE_id], + curr_pucch->resource_indicator, + O_csi, + O_ack, + O_sr); + + memset(&UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l], + 0, + sizeof(NR_sched_pucch)); + } + } +} + + +//!TODO : same function can be written to handle csi_resources +void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id) { + uint8_t csi_report_id = 0; + uint8_t csi_resourceidx =0; + uint8_t csi_ssb_idx =0; + + NR_CSI_MeasConfig_t *csi_MeasConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + NR_CSI_ResourceConfigId_t csi_ResourceConfigId; + for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + csi_ResourceConfigId=csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->resourcesForChannelMeasurement; + UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportQuantity.present; + + for ( csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) { + if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_ResourceConfigId != csi_ResourceConfigId) + continue; + else { + //Finding the CSI_RS or SSB Resources + UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type= csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.present; + if (NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB ==UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type){ + struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList__nzp_CSI_RS_SSB * nzp_CSI_RS_SSB = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB; + + UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report = nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count:0; + UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = nzp_CSI_RS_SSB->csi_SSB_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count:0; + } + + if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report){ + uint8_t nb_ssb_resources =0; + for ( 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_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { + ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig + if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled == + csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.present ) { + if (NULL != csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS) + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri = *(csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1; + else + /*! From Spec 38.331 + * nrofReportedRS + * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE + * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report. + * When the field is absent the UE applies the value 1 + */ + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 1; + } else + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 2; + + nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count; + if (nb_ssb_resources){ + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources)); + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP + } + else{ + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =0; + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 0; + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =0; + } + + LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d\n", + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen, + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen, + UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen); + break ; + } + } + } + if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report) + AssertFatal(1==0,"Currently configuring only SSB beamreporting."); + break; + } + } + } +} + + +uint16_t nr_get_csi_bitlen(int Mod_idP, + int UE_id, + uint8_t csi_report_id) { + + uint16_t csi_bitlen =0; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + CRI_SSBRI_RSRP_bitlen_t * CSI_report_bitlen = NULL; + + CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0]); + csi_bitlen = ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) + + CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen * + (CSI_report_bitlen->nb_ssbri_cri -1 )) *UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report); + + return csi_bitlen; +} + + +void nr_csi_meas_reporting(int Mod_idP, + int UE_id, + frame_t frame, + sub_frame_t slot, + int slots_per_tdd, + int ul_slots, + int n_slots_frame) { + + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_sched_pucch *curr_pucch; + NR_PUCCH_ResourceSet_t *pucchresset; + NR_CSI_ReportConfig_t *csirep; + NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; + NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup; + NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]; + NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup; + + AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count>0,"NO CSI report configuration available"); + + for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){ + + csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id]; + + AssertFatal(csirep->reportConfigType.choice.periodic!=NULL,"Only periodic CSI reporting is implemented currently"); + int period, offset, sched_slot; + csi_period_offset(csirep,&period,&offset); + sched_slot = (period+offset)%n_slots_frame; + // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214 + // preparation is done in first slot of tdd period + if ( (frame%(period/n_slots_frame)==(offset/n_slots_frame)) && (slot==((sched_slot/slots_per_tdd)*slots_per_tdd))) { + + // we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack) + curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[(sched_slot%slots_per_tdd)-slots_per_tdd+ul_slots][0]; + + NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0]; + + int found = -1; + pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 + int n_list = pucchresset->resourceList.list.count; + for (int i=0; iresourceList.list.array[i] == pucchcsires->pucch_Resource) + found = i; + } + AssertFatal(found>-1,"CSI resource not found among PUCCH resources"); + + curr_pucch->resource_indicator = found; + + n_list = pucch_Config->resourceToAddModList->list.count; + + // going through the list of PUCCH resources to find the one indexed by resource_id + for (int i=0; iresourceToAddModList->list.array[i]; + if (pucchres->pucch_ResourceId == *pucchresset->resourceList.list.array[found]) { + switch(pucchres->format.present){ + case NR_PUCCH_Resource__format_PR_format2: + if (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL) + curr_pucch->simultaneous_harqcsi = false; + else + curr_pucch->simultaneous_harqcsi = true; + break; + case NR_PUCCH_Resource__format_PR_format3: + if (pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI == NULL) + curr_pucch->simultaneous_harqcsi = false; + else + curr_pucch->simultaneous_harqcsi = true; + break; + case NR_PUCCH_Resource__format_PR_format4: + if (pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI == NULL) + curr_pucch->simultaneous_harqcsi = false; + else + curr_pucch->simultaneous_harqcsi = true; + break; + default: + AssertFatal(1==0,"Invalid PUCCH format type"); + } + } + } + curr_pucch->csi_bits += nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // TODO function to compute CSI meas report bit size + curr_pucch->frame = frame; + curr_pucch->ul_slot = sched_slot; + } + } +} + + +void handle_nr_uci_pucch_0_1(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01) +{ + int UE_id = find_nr_UE_id(mod_id, uci_01->rnti); + if (UE_id < 0) { + LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti); + return; + } + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + // tpc (power control) + sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, + uci_01->ul_cqi, + 30); + + // TODO + int max_harq_rounds = 4; // TODO define macro + if (((uci_01->pduBitmap >> 1) & 0x01)) { + // handle harq + int harq_idx_s = 0; + + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { + // search for the right harq process + for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) { + // if the gNB received ack with a good confidence + if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { + sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; + if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) && + (uci_01->harq->harq_confidence_level == 0)) { + // toggle NDI and reset round + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + } + else + sched_ctrl->harq_processes[harq_idx].round++; + sched_ctrl->harq_processes[harq_idx].is_waiting = 0; + harq_idx_s = harq_idx + 1; + // if the max harq rounds was reached + if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + UE_info->mac_stats[UE_id].dlsch_errors++; + } + break; + } + // if feedback slot processing is aborted + else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1 + && (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot + && sched_ctrl->harq_processes[harq_idx].is_waiting) { + sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; + sched_ctrl->harq_processes[harq_idx].round++; + if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + } + sched_ctrl->harq_processes[harq_idx].is_waiting = 0; + } + } + } + } +} + +void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) +{ + int UE_id = find_nr_UE_id(mod_id, uci_234->rnti); + if (UE_id < 0) { + LOG_E(MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); + return; + } + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + // tpc (power control) + sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, + uci_234->ul_cqi, + 30); + + // TODO + int max_harq_rounds = 4; // TODO define macro + if ((uci_234->pduBitmap >> 1) & 0x01) { + int harq_idx_s = 0; + int acknack; + + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) { + acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01; + for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) { + // if the gNB received ack with a good confidence or if the max harq rounds was reached + if ((slot - 1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { + // TODO add some confidence level for when there is no CRC + sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; + if ((uci_234->harq.harq_crc != 1) && acknack) { + // toggle NDI and reset round + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + } + else + sched_ctrl->harq_processes[harq_idx].round++; + sched_ctrl->harq_processes[harq_idx].is_waiting = 0; + harq_idx_s = harq_idx + 1; + // if the max harq rounds was reached + if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + UE_info->mac_stats[UE_id].dlsch_errors++; + } + break; + } + // if feedback slot processing is aborted + else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1 + && (slot - 1) > sched_ctrl->harq_processes[harq_idx].feedback_slot + && sched_ctrl->harq_processes[harq_idx].is_waiting) { + sched_ctrl->harq_processes[harq_idx].feedback_slot = -1; + sched_ctrl->harq_processes[harq_idx].round++; + if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + } + sched_ctrl->harq_processes[harq_idx].is_waiting = 0; + } + } + } + } +} + + +// function to update pucch scheduling parameters in UE list when a USS DL is scheduled +void nr_acknack_scheduling(int Mod_idP, + int UE_id, + frame_t frameP, + sub_frame_t slotP, + int slots_per_tdd, + int *pucch_id, + int *pucch_occ) { + + NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; + NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; + NR_sched_pucch *curr_pucch; + int max_acknacks,pucch_res,first_ul_slot_tdd,k,i,l; + uint8_t pdsch_to_harq_feedback[8]; + int found = 0; + int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) + nr_ulmix_slots++; + + bool csi_pres=false; + for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits>0) + csi_pres=true; + } + + // As a preference always schedule ack nacks in PUCCH0 (max 2 per slots) + // Unless there is CSI meas reporting scheduled in the period to avoid conflicts in the same slot + if (csi_pres) + max_acknacks=10; + else + max_acknacks=2; + + // this is hardcoded for now as ue specific + NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback); + + // for each possible ul or mixed slot + for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k][l]; + //if it is possible to schedule acknack in current pucch (no exclusive csi pucch) + if ((curr_pucch->csi_bits == 0) || (curr_pucch->simultaneous_harqcsi==true)) { + // if there is free room in current pucch structure + if (curr_pucch->dai_c-1){ + curr_pucch->resource_indicator = pucch_res; + curr_pucch->frame = frameP; + // first pucch occasion in first UL or MIXED slot + first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; + i = 0; + while (i<8 && found == 0) { // look if timing indicator is among allowed values + if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd)) + found = 1; + if (found == 0) i++; + } + if (found == 1) { + // computing slot in which pucch is scheduled + curr_pucch->dai_c++; + curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd)); + curr_pucch->timing_indicator = i; // index in the list of timing indicators + *pucch_id = k; + *pucch_occ = l; + return; + } + } + } + } + } + } + AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n"); +} + + +void csi_period_offset(NR_CSI_ReportConfig_t *csirep, + int *period, int *offset) { + + NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present; + + switch(p_and_o){ + case NR_CSI_ReportPeriodicityAndOffset_PR_slots4: + *period = 4; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots5: + *period = 5; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots8: + *period = 8; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots10: + *period = 10; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots16: + *period = 16; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots20: + *period = 20; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots40: + *period = 40; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots80: + *period = 80; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots160: + *period = 160; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160; + break; + case NR_CSI_ReportPeriodicityAndOffset_PR_slots320: + *period = 320; + *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320; + break; + default: + AssertFatal(1==0,"No periodicity and offset resource found in CSI report"); + } +} + + +int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l) { + + // to be updated later, for now simple implementation + // use the second allocation just in case there is csi in the first + // in that case use second resource (for a different symbol) see 9.2 in 38.213 + if (l==1) { + if (UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits==0) + return -1; + else + return 1; + } + else + return 0; + +} + + +uint16_t compute_pucch_prb_size(uint8_t format, + uint8_t nr_prbs, + uint16_t O_tot, + uint16_t O_csi, + NR_PUCCH_MaxCodeRate_t *maxCodeRate, + uint8_t Qm, + uint8_t n_symb, + uint8_t n_re_ctrl) { + + uint16_t O_crc; + + if (O_tot<12) + O_crc = 0; + else{ + if (O_tot<20) + O_crc = 6; + else { + if (O_tot<360) + O_crc = 11; + else + AssertFatal(1==0,"Case for segmented PUCCH not yet implemented"); + } + } + + int rtimes100; + switch(*maxCodeRate){ + case NR_PUCCH_MaxCodeRate_zeroDot08 : + rtimes100 = 8; + break; + case NR_PUCCH_MaxCodeRate_zeroDot15 : + rtimes100 = 15; + break; + case NR_PUCCH_MaxCodeRate_zeroDot25 : + rtimes100 = 25; + break; + case NR_PUCCH_MaxCodeRate_zeroDot35 : + rtimes100 = 35; + break; + case NR_PUCCH_MaxCodeRate_zeroDot45 : + rtimes100 = 45; + break; + case NR_PUCCH_MaxCodeRate_zeroDot60 : + rtimes100 = 60; + break; + case NR_PUCCH_MaxCodeRate_zeroDot80 : + rtimes100 = 80; + break; + default : + AssertFatal(1==0,"Invalid MaxCodeRate"); + } + + float r = (float)rtimes100/100; + + if (O_csi == O_tot) { + if ((O_tot+O_csi)>(nr_prbs*n_re_ctrl*n_symb*Qm*r)) + AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs", + r,O_tot,O_crc,nr_prbs); + else + return nr_prbs; + } + + if (format==2){ + // TODO fix this for multiple CSI reports + for (int i=1; i<=nr_prbs; i++){ + if((O_tot+O_crc)<=(i*n_symb*Qm*n_re_ctrl*r) && + (O_tot+O_crc)>((i-1)*n_symb*Qm*n_re_ctrl*r)) + return i; + } + AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with at most %d PRBs", + r,O_tot,O_crc,nr_prbs); + } + else{ + AssertFatal(1==0,"Not yet implemented"); + } + +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 84ad51f072..75b00ea6ba 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -31,7 +31,7 @@ #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "executables/softmodem-common.h" -//#define ENABLE_MAC_PAYLOAD_DEBUG 1 +#include "common/utils/nr/nr_common.h" void nr_process_mac_pdu( @@ -217,33 +217,18 @@ void nr_process_mac_pdu( log_dump(MAC, pdu_ptr + mac_subheader_len, 32, LOG_DUMP_CHAR, "\n"); #endif - if(IS_SOFTMODEM_NOS1){ - mac_rlc_data_ind(module_idP, - 0x1234, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *) (pdu_ptr + mac_subheader_len), - mac_sdu_len, - 1, - NULL); - } - else{ - mac_rlc_data_ind(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcid, - (char *) (pdu_ptr + mac_subheader_len), - mac_sdu_len, - 1, - NULL); - } + mac_rlc_data_ind(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pdu_ptr + mac_subheader_len), + mac_sdu_len, + 1, + NULL); break; @@ -261,37 +246,58 @@ void nr_process_mac_pdu( } } -void handle_nr_ul_harq(uint16_t slot, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, nfapi_nr_crc_t crc_pdu) { +void handle_nr_ul_harq(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_crc_t *crc_pdu) +{ + int UE_id = find_nr_UE_id(mod_id, crc_pdu->rnti); + if (UE_id < 0) { + LOG_E(MAC, "%s(): unknown RNTI %04x in PUSCH\n", __func__, crc_pdu->rnti); + return; + } + NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; int max_harq_rounds = 4; // TODO define macro - uint8_t hrq_id = crc_pdu.harq_id; + uint8_t hrq_id = crc_pdu->harq_id; NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id]; if (cur_harq->state==ACTIVE_SCHED) { - if (!crc_pdu.tb_crc_status) { + if (!crc_pdu->tb_crc_status) { cur_harq->ndi ^= 1; cur_harq->round = 0; cur_harq->state = INACTIVE; // passed -> make inactive. can be used by scheduder for next grant -#ifdef UL_HARQ_PRINT - printf("[HARQ HANDLER] Ulharq id %d crc passed, freeing it for scheduler\n",hrq_id); -#endif + LOG_D(MAC, + "Ulharq id %d crc passed for RNTI %04x\n", + hrq_id, + crc_pdu->rnti); } else { cur_harq->round++; cur_harq->state = ACTIVE_NOT_SCHED; -#ifdef UL_HARQ_PRINT - printf("[HARQ HANDLER] Ulharq id %d crc failed, requesting retransmission\n",hrq_id); -#endif + LOG_D(MAC, + "Ulharq id %d crc failed for RNTI %04x\n", + hrq_id, + crc_pdu->rnti); } if (!(cur_harq->roundndi ^= 1; cur_harq->state = INACTIVE; // failed after 4 rounds -> make inactive cur_harq->round = 0; - LOG_D(MAC,"[HARQ HANDLER] RNTI %x: Ulharq id %d crc failed in all round, freeing it for scheduler\n",crc_pdu.rnti,hrq_id); - stats->ulsch_errors++; + LOG_D(MAC, + "RNTI %04x: Ulharq id %d crc failed in all rounds\n", + crc_pdu->rnti, + hrq_id); + UE_info->mac_stats[UE_id].ulsch_errors++; } return; } else - LOG_E(MAC,"Incorrect ULSCH HARQ process %d or invalid state %d\n",hrq_id,cur_harq->state); + LOG_W(MAC, + "Incorrect ULSCH HARQ PID %d or invalid state %d for RNTI %04x " + "(ignore this warning for RA)\n", + hrq_id, + cur_harq->state, + crc_pdu->rnti); } /* @@ -399,6 +405,11 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, bwpList->list.count); const int bwp_id = 1; UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1]; + struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList; + AssertFatal(ubwpList->list.count == 1, + "uplinkBWP_ToAddModList has %d BWP!\n", + ubwpList->list.count); + UE_info->UE_sched_ctrl[UE_id].active_ubwp = ubwpList->list.array[bwp_id - 1]; LOG_I(MAC, "[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, " "adding UE MAC Context UE_id %d/RNTI %04x\n", @@ -415,8 +426,389 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, "reset RA state information for RA-RNTI %04x/index %d\n", ra->rnti, i); + return; } } +} +long get_K2(NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) { + DevAssert(ubwp); + const NR_PUSCH_TimeDomainResourceAllocation_t *tda_list = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]; + if (tda_list->k2) + return *tda_list->k2; + else if (mu < 2) + return 1; + else if (mu == 2) + return 2; + else + return 3; +} + +int8_t select_ul_harq_pid(NR_UE_sched_ctrl_t *sched_ctrl) { + const uint8_t max_ul_harq_pids = 3; // temp: for testing + // schedule active harq processes + for (uint8_t hrq_id = 0; hrq_id < max_ul_harq_pids; hrq_id++) { + NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id]; + if (cur_harq->state == ACTIVE_NOT_SCHED) { + LOG_D(MAC, "Found ulharq id %d, scheduling it for retransmission\n", hrq_id); + return hrq_id; + } + } + + // schedule new harq processes + for (uint8_t hrq_id=0; hrq_id < max_ul_harq_pids; hrq_id++) { + NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[hrq_id]; + if (cur_harq->state == INACTIVE) { + LOG_D(MAC, "Found new ulharq id %d, scheduling it\n", hrq_id); + return hrq_id; + } + } + LOG_E(MAC, "All UL HARQ processes are busy. Cannot schedule ULSCH\n"); + return -1; +} + +void nr_simple_ulsch_preprocessor(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + int num_slots_per_tdd, + uint64_t ulsch_in_slot_bitmap) { + gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + NR_COMMON_channels_t *cc = nr_mac->common_channels; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + NR_UE_info_t *UE_info = &nr_mac->UE_info; + + AssertFatal(UE_info->num_UEs <= 1, + "%s() cannot handle more than one UE, but found %d\n", + __func__, + UE_info->num_UEs); + if (UE_info->num_UEs == 0) + return; + + const int UE_id = 0; + const int CC_id = 0; + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + const int tda = 1; + const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = + sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; + AssertFatal(tda < tdaList->list.count, + "time domain assignment %d >= %d\n", + tda, + tdaList->list.count); + int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu); + const int sched_frame = frame + (slot + K2 >= num_slots_per_tdd); + const int sched_slot = (slot + K2) % num_slots_per_tdd; + if (!is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot)) + return; + + /* get first, largest unallocated region */ + uint16_t *vrb_map_UL = + &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * 275]; + uint16_t rbStart = 0; + while (vrb_map_UL[rbStart]) rbStart++; + const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); + uint16_t rbSize = 1; + while (rbStart + rbSize < bwpSize && !vrb_map_UL[rbStart+rbSize]) + rbSize++; + + sched_ctrl->sched_pusch.slot = sched_slot; + sched_ctrl->sched_pusch.frame = sched_frame; + + const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss); + uint8_t nr_of_candidates; + find_aggregation_candidates(&sched_ctrl->aggregation_level, + &nr_of_candidates, + sched_ctrl->search_space); + sched_ctrl->coreset = get_coreset( + sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */); + const int cid = sched_ctrl->coreset->controlResourceSetId; + const uint16_t Y = UE_info->Y[UE_id][cid][slot]; + const int m = UE_info->num_pdcch_cand[UE_id][cid]; + sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id], + sched_ctrl->active_bwp, + sched_ctrl->coreset, + sched_ctrl->aggregation_level, + Y, + m, + nr_of_candidates); + if (sched_ctrl->cce_index < 0) { + LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PUSCH\n", __func__); + return; + } + UE_info->num_pdcch_cand[UE_id][cid]++; + + sched_ctrl->sched_pusch.time_domain_allocation = tda; + const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats; + const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0; + const uint8_t num_dmrs_cdm_grps_no_data = 1; + /* we want to avoid a lengthy deduction of DMRS and other parameters in + * every TTI if we can save it, so check whether dci_format, TDA, or + * num_dmrs_cdm_grps_no_data has changed and only then recompute */ + NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save; + if (ps->time_domain_allocation != tda + || ps->dci_format != dci_format + || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data) + nr_save_pusch_fields(scc, + sched_ctrl->active_ubwp, + dci_format, + tda, + num_dmrs_cdm_grps_no_data, + ps); + + const int mcs = 9; + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + sched_pusch->mcs = mcs; + sched_pusch->rbStart = rbStart; + sched_pusch->rbSize = rbSize; + + /* Calculate TBS from MCS */ + sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table); + sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table); + if (ps->pusch_Config->tp_pi2BPSK + && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) { + sched_pusch->R >>= 1; + sched_pusch->Qm <<= 1; + } + sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm, + sched_pusch->R, + sched_pusch->rbSize, + ps->nrOfSymbols, + ps->N_PRB_DMRS * ps->num_dmrs_symb, + 0, // nb_rb_oh + 0, + 1 /* NrOfLayers */) + >> 3; + + /* mark the corresponding RBs as used */ + for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++) + vrb_map_UL[rb + sched_ctrl->sched_pusch.rbStart] = 1; +} + +void nr_schedule_ulsch(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + int num_slots_per_tdd, + int ul_slots, + uint64_t ulsch_in_slot_bitmap) { + RC.nrmac[module_id]->pre_processor_ul( + module_id, frame, slot, num_slots_per_tdd, ulsch_in_slot_bitmap); + + NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[0].ServingCellConfigCommon; + NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info; + const NR_UE_list_t *UE_list = &UE_info->list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + /* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in + * every TTI are pre-populated by the preprocessor and used below */ + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + if (sched_pusch->rbSize <= 0) + continue; + + uint16_t rnti = UE_info->rnti[UE_id]; + + int8_t harq_id = select_ul_harq_pid(sched_ctrl); + if (harq_id < 0) return; + NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[harq_id]; + cur_harq->state = ACTIVE_SCHED; + cur_harq->last_tx_slot = sched_pusch->slot; + + int rnti_types[2] = { NR_RNTI_C, 0 }; + + /* pre-computed PUSCH values that only change if time domain allocation, + * DCI format, or DMRS parameters change. Updated in the preprocessor + * through nr_save_pusch_fields() */ + NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save; + + /* Statistics */ + UE_info->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++; + if (cur_harq->round == 0) { + UE_info->mac_stats[UE_id].ulsch_total_bytes_scheduled += sched_pusch->tb_size; + } else { + LOG_W(MAC, + "%d.%2d UL retransmission RNTI %04x sched %d.%2d HARQ PID %d round %d NDI %d\n", + frame, + slot, + rnti, + sched_pusch->frame, + sched_pusch->slot, + harq_id, + cur_harq->round, + cur_harq->ndi); + } + + LOG_D(MAC, + "%4d.%2d RNTI %04x UL sched %4d.%2d start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n", + frame, + slot, + rnti, + sched_pusch->frame, + sched_pusch->slot, + sched_pusch->rbStart, + sched_pusch->rbSize, + sched_pusch->mcs, + sched_pusch->tb_size, + harq_id, + cur_harq->round, + cur_harq->ndi); + + /* PUSCH in a later slot, but corresponding DCI now! */ + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_id]->UL_tti_req_ahead[0][sched_pusch->slot]; + AssertFatal(future_ul_tti_req->SFN == sched_pusch->frame + && future_ul_tti_req->Slot == sched_pusch->slot, + "%d.%d future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", + frame, slot, + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + sched_pusch->frame, + sched_pusch->slot); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; + memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); + future_ul_tti_req->n_pdus += 1; + + LOG_D(MAC, "%4d.%2d Scheduling UE specific PUSCH\n", frame, slot); + + pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + pusch_pdu->rnti = rnti; + pusch_pdu->handle = 0; //not yet used + + /* FAPI: BWP */ + pusch_pdu->bwp_size = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); + pusch_pdu->bwp_start = NRRIV2PRBOFFSET(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth,275); + pusch_pdu->subcarrier_spacing = sched_ctrl->active_ubwp->bwp_Common->genericParameters.subcarrierSpacing; + pusch_pdu->cyclic_prefix = 0; + + /* FAPI: PUSCH information always included */ + pusch_pdu->target_code_rate = sched_pusch->R; + pusch_pdu->qam_mod_order = sched_pusch->Qm; + pusch_pdu->mcs_index = sched_pusch->mcs; + pusch_pdu->mcs_table = ps->mcs_table; + pusch_pdu->transform_precoding = ps->transform_precoding; + if (ps->pusch_Config->dataScramblingIdentityPUSCH) + pusch_pdu->data_scrambling_id = *ps->pusch_Config->dataScramblingIdentityPUSCH; + else + pusch_pdu->data_scrambling_id = *scc->physCellId; + pusch_pdu->nrOfLayers = 1; + + /* FAPI: DMRS */ + pusch_pdu->ul_dmrs_symb_pos = ps->ul_dmrs_symb_pos; + pusch_pdu->dmrs_config_type = ps->dmrs_config_type; + if (pusch_pdu->transform_precoding) { // transform precoding disabled + long *scramblingid; + if (pusch_pdu->scid == 0) + scramblingid = ps->NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; + else + scramblingid = ps->NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; + if (scramblingid == NULL) + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + else + pusch_pdu->ul_dmrs_scrambling_id = *scramblingid; + } + else { + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + if (ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) + pusch_pdu->pusch_identity = *ps->NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; + else + pusch_pdu->pusch_identity = *scc->physCellId; + } + pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] + pusch_pdu->num_dmrs_cdm_grps_no_data = ps->num_dmrs_cdm_grps_no_data; + pusch_pdu->dmrs_ports = 1; + + /* FAPI: Pusch Allocation in frequency domain */ + AssertFatal(ps->pusch_Config->resourceAllocation == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1, + "Only frequency resource allocation type 1 is currently supported\n"); + pusch_pdu->resource_alloc = 1; //type 1 + pusch_pdu->rb_start = sched_pusch->rbStart; + pusch_pdu->rb_size = sched_pusch->rbSize; + pusch_pdu->vrb_to_prb_mapping = 0; + if (ps->pusch_Config->frequencyHopping==NULL) + pusch_pdu->frequency_hopping = 0; + else + pusch_pdu->frequency_hopping = 1; + + /* FAPI: Resource Allocation in time domain */ + pusch_pdu->start_symbol_index = ps->startSymbolIndex; + pusch_pdu->nr_of_symbols = ps->nrOfSymbols; + + /* PUSCH PDU */ + pusch_pdu->pusch_data.rv_index = nr_rv_round_map[cur_harq->round]; + pusch_pdu->pusch_data.harq_process_id = harq_id; + pusch_pdu->pusch_data.new_data_indicator = cur_harq->ndi; + pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size; + pusch_pdu->pusch_data.num_cb = 0; //CBG not supported + + /* PUSCH PTRS */ + if (ps->NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { + // TODO to be fixed from RRC config + uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig + uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig + uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig + uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig + uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig + pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); + pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); + pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); + pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + + pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + } + else{ + pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + } + + nfapi_nr_ul_dci_request_t *ul_dci_req = &RC.nrmac[module_id]->UL_dci_req[0]; + ul_dci_req->SFN = frame; + ul_dci_req->Slot = slot; + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; + memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); + ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; + ul_dci_req->numPdus += 1; + + LOG_D(MAC,"Configuring ULDCI/PDCCH in %d.%d\n", frame,slot); + + nr_configure_pdcch(RC.nrmac[0], + pdcch_pdu_rel15, + rnti, + sched_ctrl->search_space, + sched_ctrl->coreset, + scc, + sched_ctrl->active_bwp, + sched_ctrl->aggregation_level, + sched_ctrl->cce_index); + + dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; + memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15)); + NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id]; + const int n_ubwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; + // NOTE: below functions assume that dci_formats is an array corresponding + // to all UL DCIs in the PDCCH, but for us it is a simple int. So before + // having multiple UEs, the below need to be changed (IMO the functions + // should fill for one DCI only and not handle all of them). + config_uldci(sched_ctrl->active_ubwp, + pusch_pdu, + pdcch_pdu_rel15, + &dci_pdu_rel15[0], + &ps->dci_format, + ps->time_domain_allocation, + UE_info->UE_sched_ctrl[UE_id].tpc0, + n_ubwp, + sched_ctrl->active_bwp->bwp_Id); + fill_dci_pdu_rel15(scc, + secondaryCellGroup, + pdcch_pdu_rel15, + dci_pdu_rel15, + &ps->dci_format, + rnti_types, + pusch_pdu->bwp_size, + sched_ctrl->active_bwp->bwp_Id); + + memset(sched_pusch, 0, sizeof(*sched_pusch)); + } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index b3cd91fd01..c4b2f5503e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -88,6 +88,20 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id, void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, uint8_t slots_per_frame); +/// uplink scheduler +void nr_schedule_ulsch(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + int num_slots_per_tdd, + int ul_slots, + uint64_t ulsch_in_slot_bitmap); + +void nr_simple_ulsch_preprocessor(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + int num_slots_per_tdd, + uint64_t ulsch_in_slot_bitmap); + /////// Random Access MAC-PHY interface functions and primitives /////// void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); @@ -107,7 +121,9 @@ void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP); int nr_allocate_CCEs(int module_idP, int CC_idP, frame_t frameP, sub_frame_t slotP, int test_only); -void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc, +void nr_get_Msg3alloc(module_id_t module_id, + int CC_id, + NR_ServingCellConfigCommon_t *scc, NR_BWP_Uplink_t *ubwp, sub_frame_t current_subframe, frame_t current_frame, @@ -136,6 +152,13 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot, int num_slots_per_tdd); +/* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a + * fixed set of resources */ +void nr_ul_preprocessor_phytest(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + int num_slots_per_tdd, + uint64_t ulsch_in_slot_bitmap); void nr_schedule_css_dlsch_phytest(module_id_t module_idP, frame_t frameP, @@ -157,32 +180,33 @@ void nr_fill_nfapi_dl_pdu(int Mod_id, int ndi, int round); -void nr_rx_acknack(nfapi_nr_uci_pusch_pdu_t *uci_pusch, - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01, - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234, - NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats); +void handle_nr_uci_pucch_0_1(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01); +void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234); + void config_uldci(NR_BWP_Uplink_t *ubwp, nfapi_nr_pusch_pdu_t *pusch_pdu, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, - int *dci_formats, int *rnti_types, + int *dci_formats, int time_domain_assignment, uint8_t tpc, int n_ubwp, int bwp_id); -void nr_schedule_pusch(int Mod_idP, - int UE_id, - int num_slots_per_tdd, - int ul_slots, - frame_t frameP, - sub_frame_t slotP); - void nr_schedule_pucch(int Mod_idP, int UE_id, int nr_ulmix_slots, frame_t frameP, sub_frame_t slotP); +void csi_period_offset(NR_CSI_ReportConfig_t *csirep, + int *period, int *offset); + void nr_csi_meas_reporting(int Mod_idP, int UE_id, frame_t frameP, @@ -276,6 +300,15 @@ void find_aggregation_candidates(uint8_t *aggregation_level, uint8_t *nr_of_candidates, NR_SearchSpace_t *ss); +long get_K2(NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu); + +void nr_save_pusch_fields(const NR_ServingCellConfigCommon_t *scc, + const NR_BWP_Uplink_t *ubwp, + long dci_format, + int tda, + uint8_t num_dmrs_cdm_grps_no_data, + NR_sched_pusch_save_t *ps); + uint8_t nr_get_tpc(int target, uint8_t cqi, int incr); int get_spf(nfapi_nr_config_request_scf_t *cfg); @@ -350,16 +383,6 @@ void nr_generate_Msg2(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); -void nr_schedule_reception_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP); - -void schedule_fapi_ul_pdu(int Mod_idP, - frame_t frameP, - sub_frame_t slotP, - int num_slots_per_tdd, - int ul_slots, - int time_domain_assignment, - uint64_t ulsch_in_slot_bitmap); - void nr_process_mac_pdu( module_id_t module_idP, rnti_t rnti, @@ -395,7 +418,10 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, const uint8_t ul_cqi, const uint16_t rssi); -void handle_nr_ul_harq(uint16_t slot, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, nfapi_nr_crc_t crc_pdu); +void handle_nr_ul_harq(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + const nfapi_nr_crc_t *crc_pdu); int16_t ssb_index_from_prach(module_id_t module_idP, frame_t frameP, @@ -406,5 +432,4 @@ int16_t ssb_index_from_prach(module_id_t module_idP, void find_SSB_and_RO_available(module_id_t module_idP); -void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, int target_snrx10); #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index b7db1f67aa..78a0dbb649 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -34,7 +34,6 @@ #include "NR_MAC_COMMON/nr_mac_extern.h" #include "assertions.h" -#include "LAYER2/PDCP_v10.1.0/pdcp.h" #include "LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "RRC/NR/nr_rrc_defs.h" #include "common/utils/LOG/log.h" @@ -82,10 +81,13 @@ void mac_top_init_gNB(void) RC.nrmac[i]->ul_handle = 0; - if (get_softmodem_params()->phy_test) + if (get_softmodem_params()->phy_test) { RC.nrmac[i]->pre_processor_dl = nr_preprocessor_phytest; - else + RC.nrmac[i]->pre_processor_ul = nr_ul_preprocessor_phytest; + } else { RC.nrmac[i]->pre_processor_dl = nr_simple_dlsch_preprocessor; + RC.nrmac[i]->pre_processor_ul = nr_simple_ulsch_preprocessor; + } }//END for (i = 0; i < RC.nb_nr_macrlc_inst; i++) @@ -94,8 +96,8 @@ void mac_top_init_gNB(void) // These should be out of here later pdcp_layer_init(); - if(IS_SOFTMODEM_NOS1) - nr_DRB_preconfiguration(); + if(IS_SOFTMODEM_NOS1 && !get_softmodem_params()->do_ra) + nr_DRB_preconfiguration(0x1234); rrc_init_nr_global_param(); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 656d1c3e7c..d6a5cbf6ba 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -62,8 +62,6 @@ #include "NR_PHY_INTERFACE/NR_IF_Module.h" /* MAC */ -#include "LAYER2/MAC/mac.h" -#include "LAYER2/MAC/mac_proto.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" #include "NR_TAG.h" @@ -142,8 +140,6 @@ typedef struct { uint8_t msg3_cqireq; /// Round of Msg3 HARQ uint8_t msg3_round; - /// Msg3 pusch pdu - nfapi_nr_pusch_pdu_t pusch_pdu; /// TBS used for Msg4 int msg4_TBsize; /// MCS used for Msg4 @@ -192,8 +188,9 @@ typedef struct { NR_RA_t ra[NR_NB_RA_PROC_MAX]; /// VRB map for common channels uint16_t vrb_map[275]; - /// VRB map for common channels and retransmissions by PHICH - uint16_t vrb_map_UL[275]; + /// VRB map for common channels and PUSCH, dynamically allocated because + /// length depends on number of slots and RBs + uint16_t *vrb_map_UL; /// number of subframe allocation pattern available for MBSFN sync area uint8_t num_sf_allocation_pattern; ///Number of active SSBs @@ -285,12 +282,49 @@ typedef struct NR_sched_pucch { uint8_t resource_indicator; } NR_sched_pucch; +/* this struct is a helper: as long as the TDA and DCI format remain the same + * over the same uBWP and search space, there is no need to recalculate all + * S/L, MCS table, or DMRS-related parameters over and over again. Hence, we + * store them in this struct for easy reference. */ +typedef struct NR_sched_pusch_save { + int dci_format; + int time_domain_allocation; + uint8_t num_dmrs_cdm_grps_no_data; + + int startSymbolIndex; + int nrOfSymbols; + + NR_PUSCH_Config_t *pusch_Config; + uint8_t transform_precoding; + uint8_t mcs_table; + + long mapping_type; + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig; + uint16_t dmrs_config_type; + uint16_t ul_dmrs_symb_pos; + uint8_t num_dmrs_symb; + uint8_t N_PRB_DMRS; +} NR_sched_pusch_save_t; + typedef struct NR_sched_pusch { int frame; int slot; - bool active; - nfapi_nr_pusch_pdu_t pusch_pdu; -} NR_sched_pusch; + + /// RB allocation within active uBWP + uint16_t rbSize; + uint16_t rbStart; + + // time-domain allocation for scheduled RBs + int time_domain_allocation; + + /// MCS + uint8_t mcs; + + /// TBS-related info + uint16_t R; + uint8_t Qm; + uint32_t tb_size; +} NR_sched_pusch_t; typedef struct NR_UE_harq { uint8_t is_waiting; @@ -348,11 +382,15 @@ typedef struct { /// the currently active BWP in DL NR_BWP_Downlink_t *active_bwp; + /// the currently active BWP in UL + NR_BWP_Uplink_t *active_ubwp; + NR_sched_pucch **sched_pucch; /// selected PUCCH index, if scheduled int pucch_sched_idx; int pucch_occ_idx; - NR_sched_pusch *sched_pusch; + NR_sched_pusch_save_t pusch_save; + NR_sched_pusch_t sched_pusch; /// CCE index and aggregation, should be coherent with cce_list NR_SearchSpace_t *search_space; @@ -381,7 +419,6 @@ typedef struct { uint8_t tpc0; uint8_t tpc1; uint16_t ul_rssi; - uint8_t current_harq_pid; NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES]; NR_UE_ul_harq_t ul_harq_processes[NR_MAX_NB_HARQ_PROCESSES]; int dummy; @@ -418,7 +455,6 @@ typedef struct { /*! \brief UE list used by gNB to order UEs/CC for scheduling*/ #define MAX_CSI_REPORTCONFIG 48 typedef struct { - DLSCH_PDU DLSCH_pdu[4][MAX_MOBILES_PER_GNB]; /// scheduling control info nr_csi_report_t csi_report_template[MAX_MOBILES_PER_GNB][MAX_CSI_REPORTCONFIG]; NR_UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB]; @@ -441,6 +477,11 @@ typedef void (*nr_pp_impl_dl)(module_id_t mod_id, frame_t frame, sub_frame_t slot, int num_slots_per_tdd); +typedef void (*nr_pp_impl_ul)(module_id_t mod_id, + frame_t frame, + sub_frame_t slot, + int num_slots_per_tdd, + uint64_t ulsch_in_slot_bitmap); /*! \brief top level eNB MAC structure */ typedef struct gNB_MAC_INST_s { @@ -467,8 +508,12 @@ typedef struct gNB_MAC_INST_s { nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX]; /// NFAPI DL Config Request Structure nfapi_nr_dl_tti_request_t DL_req[NFAPI_CC_MAX]; - /// NFAPI UL TTI Request Structure (this is from the new SCF specs) - nfapi_nr_ul_tti_request_t UL_tti_req[NFAPI_CC_MAX]; + /// NFAPI UL TTI Request Structure, simple pointer into structure + /// UL_tti_req_ahead for current frame/slot + nfapi_nr_ul_tti_request_t *UL_tti_req[NFAPI_CC_MAX]; + /// NFAPI UL TTI Request Structure for future TTIs, dynamically allocated + /// because length depends on number of slots + nfapi_nr_ul_tti_request_t *UL_tti_req_ahead[NFAPI_CC_MAX]; /// NFAPI HI/DCI0 Config Request Structure nfapi_nr_ul_dci_request_t UL_dci_req[NFAPI_CC_MAX]; /// NFAPI DL PDU structure @@ -478,6 +523,7 @@ typedef struct gNB_MAC_INST_s { /// UL handle uint32_t ul_handle; + //UE_info_t UE_info; // MAC function execution peformance profiler /// processing time of eNB scheduler @@ -502,11 +548,11 @@ typedef struct gNB_MAC_INST_s { time_stats_t schedule_pch; /// CCE lists int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE]; - /// current slot - int current_slot; /// DL preprocessor for differentiated scheduling nr_pp_impl_dl pre_processor_dl; + /// UL preprocessor for differentiated scheduling + nr_pp_impl_ul pre_processor_ul; } gNB_MAC_INST; #endif /*__LAYER2_NR_MAC_GNB_H__ */ diff --git a/openair2/LAYER2/nr_pdcp/asn1_utils.c b/openair2/LAYER2/nr_pdcp/asn1_utils.c new file mode 100644 index 0000000000..264a2815bb --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/asn1_utils.c @@ -0,0 +1,68 @@ +/* + * 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 "pdcp.h" + +int decode_t_reordering(int v) +{ + static int tab[36] = { + 0, 1, 2, 4, 5, 8, 10, 15, 20, 30, 40, 50, 60, 80, 100, 120, 140, 160, 180, + 200, 220, 240, 260, 280, 300, 500, 750, 1000, 1250, 1500, 1750, 2000, + 2250, 2500, 2750, 3000 + }; + + if (v < 0 || v > 35) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_sn_size_ul(long s) +{ + if (s == 0) return 12; + if (s == 1) return 18; + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); +} + +int decode_sn_size_dl(long s) +{ + if (s == 0) return 12; + if (s == 1) return 18; + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); +} + +int decode_discard_timer(long v) +{ + static int tab[16] = { + 10, 20, 30, 40, 50, 60, 75, 100, 150, 200, 250, 300, 500, 750, 1500, -1, + }; + + if (v < 0 || v > 15) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} diff --git a/openair2/LAYER2/nr_pdcp/asn1_utils.h b/openair2/LAYER2/nr_pdcp/asn1_utils.h new file mode 100644 index 0000000000..d525bce287 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/asn1_utils.h @@ -0,0 +1,30 @@ +/* + * 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_LAYER2_NR_PDCP_ASN1_UTILS_H_ +#define _OPENAIR2_LAYER2_NR_PDCP_ASN1_UTILS_H_ + +int decode_t_reordering(int v); +int decode_sn_size_ul(long s); +int decode_sn_size_dl(long s); +int decode_discard_timer(long v); + +#endif /* _OPENAIR2_LAYER2_NR_PDCP_ASN1_UTILS_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index e25201c22c..f3d4b16130 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -44,7 +44,10 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( void *deliver_sdu_data, void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size, int sdu_id), - void *deliver_pdu_data) + void *deliver_pdu_data, + int sn_size, + int t_reordering, + int discard_timer) { nr_pdcp_entity_drb_am_t *ret; @@ -66,9 +69,12 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( ret->common.deliver_pdu = deliver_pdu; ret->common.deliver_pdu_data = deliver_pdu_data; - ret->rb_id = rb_id; + ret->rb_id = rb_id; + ret->sn_size = sn_size; + ret->t_reordering = t_reordering; + ret->discard_timer = discard_timer; - ret->common.maximum_nr_pdcp_sn = 4095; + ret->common.maximum_nr_pdcp_sn = (1 << sn_size) - 1; return (nr_pdcp_entity_t *)ret; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 45555ad6af..ce5dd300e9 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -19,6 +19,8 @@ * contact@openairinterface.org */ +#include + #ifndef _NR_PDCP_ENTITY_H_ #define _NR_PDCP_ENTITY_H_ @@ -58,8 +60,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity_drb_am( void *deliver_sdu_data, void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size, int sdu_id), - void *deliver_pdu_data); + void *deliver_pdu_data, + int sn_size, + int t_reordering, + int discard_timer); -void nr_DRB_preconfiguration(void); +void nr_DRB_preconfiguration(uint16_t crnti); #endif /* _NR_PDCP_ENTITY_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c index 85f638d66d..f2f849b9e3 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c @@ -24,13 +24,17 @@ #include #include #include +#include "common/utils/LOG/log.h" void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *_entity, char *buffer, int size) { nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; if (size < 3) abort(); - if (!(buffer[0] & 0x80)) { printf("%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } + + if (!(buffer[0] & 0x80)) + LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + entity->common.deliver_sdu(entity->common.deliver_sdu_data, (nr_pdcp_entity_t *)entity, buffer+3, size-3); } @@ -40,7 +44,7 @@ void nr_pdcp_entity_drb_am_recv_sdu(nr_pdcp_entity_t *_entity, char *buffer, int { nr_pdcp_entity_drb_am_t *entity = (nr_pdcp_entity_drb_am_t *)_entity; int sn; - char buf[size+2]; + char buf[size+3]; sn = entity->common.next_nr_pdcp_tx_sn; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h index faa8226e93..d7c42e6a62 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.h @@ -27,6 +27,9 @@ typedef struct { nr_pdcp_entity_t common; int rb_id; + int sn_size; /* unit: bits */ + int t_reordering; /* unit: ms */ + int discard_timer; /* unit: ms, -1 means infinity */ } nr_pdcp_entity_drb_am_t; void nr_pdcp_entity_drb_am_recv_pdu(nr_pdcp_entity_t *entity, char *buffer, int size); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index ca37026e54..9b33b2715d 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -22,14 +22,17 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include "asn1_utils.h" #include "nr_pdcp_ue_manager.h" #include "NR_RadioBearerConfig.h" #include "NR_RLC-BearerConfig.h" +#include "NR_RLC-Config.h" #include "NR_CellGroupConfig.h" #include "openair2/RRC/NR/nr_rrc_proto.h" /* from OAI */ #include "pdcp.h" +#include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #define TODO do { \ printf("%s:%d:%s: todo\n", __FILE__, __LINE__, __FUNCTION__); \ @@ -410,7 +413,6 @@ static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity, len = write(nas_sock_fd[0], buf, size); if (len != size) { LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); - exit(1); } } else{ @@ -595,8 +597,17 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s) nr_pdcp_ue_t *ue; int drb_id = s->drb_Identity; + int t_reordering = decode_t_reordering(*s->pdcp_Config->t_Reordering); + int sn_size_ul = decode_sn_size_ul(*s->pdcp_Config->drb->pdcp_SN_SizeUL); + int sn_size_dl = decode_sn_size_dl(*s->pdcp_Config->drb->pdcp_SN_SizeDL); + int discard_timer = decode_discard_timer(*s->pdcp_Config->drb->discardTimer); -printf("\n\n################# rnti %d add drb %d\n\n\n", rnti, drb_id); + /* TODO(?): accept different UL and DL SN sizes? */ + if (sn_size_ul != sn_size_dl) { + LOG_E(PDCP, "%s:%d:%s: fatal, bad SN sizes, must be same. ul=%d, dl=%d\n", + __FILE__, __LINE__, __FUNCTION__, sn_size_ul, sn_size_dl); + exit(1); + } if (drb_id != 1) { LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id %d\n", @@ -610,11 +621,11 @@ printf("\n\n################# rnti %d add drb %d\n\n\n", rnti, drb_id); LOG_D(PDCP, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { - pdcp_drb = new_nr_pdcp_entity_drb_am(drb_id, deliver_sdu_drb, ue, deliver_pdu_drb, ue); + pdcp_drb = new_nr_pdcp_entity_drb_am(drb_id, deliver_sdu_drb, ue, deliver_pdu_drb, ue, + sn_size_dl, t_reordering, discard_timer); nr_pdcp_ue_add_drb_pdcp_entity(ue, drb_id, pdcp_drb); - LOG_D(PDCP, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_D(PDCP, "%s:%d:%s: added drb %d to ue rnti %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } @@ -635,6 +646,7 @@ static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_Config_t *rlc_Co __FILE__, __LINE__, __FUNCTION__); exit(1); } + LOG_I(PDCP, "%s:%s:%d: added DRB for UE RNTI %x\n", __FILE__, __FUNCTION__, __LINE__, rnti); } boolean_t nr_rrc_pdcp_config_asn1_req( @@ -681,7 +693,6 @@ boolean_t nr_rrc_pdcp_config_asn1_req( if (drb2add_list != NULL) { for (i = 0; i < drb2add_list->list.count; i++) { - LOG_I(PDCP, "Before calling add_drb \n"); add_drb(rnti, drb2add_list->list.array[i], rlc_bearer2add_list->list.array[i]->rlc_Config); } } @@ -716,7 +727,7 @@ boolean_t rrc_pdcp_config_asn1_req( return 0; } -void nr_DRB_preconfiguration(void) +void nr_DRB_preconfiguration(uint16_t crnti) { NR_RadioBearerConfig_t *rbconfig = NULL; @@ -768,67 +779,19 @@ void nr_DRB_preconfiguration(void) xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); - NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig)); - - RLC_BearerConfig->logicalChannelIdentity = 4; - RLC_BearerConfig->servedRadioBearer = calloc(1,sizeof(*RLC_BearerConfig->servedRadioBearer)); - RLC_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity; - - RLC_BearerConfig->servedRadioBearer->choice.drb_Identity=1; - RLC_BearerConfig->reestablishRLC=calloc(1,sizeof(*RLC_BearerConfig->reestablishRLC)); - *RLC_BearerConfig->reestablishRLC=NR_RLC_BearerConfig__reestablishRLC_true; - RLC_BearerConfig->rlc_Config=calloc(1,sizeof(*RLC_BearerConfig->rlc_Config)); - - // RLC UM Bi-directional Bearer configuration - RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_um_Bi_Directional; - RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional)); - RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; - - RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; - RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = NR_T_Reassembly_ms15; - - // RLC AM Bearer configuration - /*RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_am; - RLC_BearerConfig->rlc_Config->choice.am = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am)); - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_p64; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_kB500; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t32; - - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15; - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15;*/ - - RLC_BearerConfig->mac_LogicalChannelConfig = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig)); - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters)); - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority = 1; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedServingCells = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedSCS_List = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->maxPUSCH_Duration = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->configuredGrantType1Allowed = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup)); - *RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = 1; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = false; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = false; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL; + nr_rlc_bearer_init(RLC_BearerConfig); + nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional); + nr_rlc_bearer_init_ul_spec(RLC_BearerConfig->mac_LogicalChannelConfig); Rlc_Bearer_ToAdd_list = calloc(1,sizeof(*Rlc_Bearer_ToAdd_list)); ASN_SEQUENCE_ADD(&Rlc_Bearer_ToAdd_list->list, RLC_BearerConfig); if (ENB_NAS_USE_TUN){ - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_YES, 0x1234, 0, 0,0); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_YES, crnti, 0, 0, 0); } else{ - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, crnti, 0, 0,0); } nr_rrc_pdcp_config_asn1_req( @@ -850,6 +813,9 @@ void nr_DRB_preconfiguration(void) rbconfig->drb_ToReleaseList, (LTE_PMCH_InfoList_r9_t *) NULL, Rlc_Bearer_ToAdd_list); + + LOG_D(PDCP, "%s:%d: done RRC PDCP/RLC ASN1 request for UE rnti %x\n", __FUNCTION__, __LINE__, ctxt.rnti); + } uint64_t get_pdcp_optmask(void) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 3a46f913e9..2f0d46afac 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -27,6 +27,7 @@ #include "asn1_utils.h" #include "nr_rlc_ue_manager.h" #include "nr_rlc_entity.h" +#include "nr_rlc_oai_api.h" #include "NR_RLC-BearerConfig.h" #include "NR_DRB-ToAddMod.h" #include "NR_DRB-ToAddModList.h" @@ -44,6 +45,76 @@ static uint64_t nr_rlc_current_time; static int nr_rlc_current_time_last_frame; static int nr_rlc_current_time_last_subframe; +void nr_rlc_bearer_init(NR_RLC_BearerConfig_t *RLC_BearerConfig){ + + + RLC_BearerConfig->servedRadioBearer = calloc(1, sizeof(*RLC_BearerConfig->servedRadioBearer)); + RLC_BearerConfig->reestablishRLC = calloc(1, sizeof(*RLC_BearerConfig->reestablishRLC)); + RLC_BearerConfig->rlc_Config = calloc(1, sizeof(*RLC_BearerConfig->rlc_Config)); + RLC_BearerConfig->mac_LogicalChannelConfig = calloc(1, sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig)); + + RLC_BearerConfig->logicalChannelIdentity = 4; + RLC_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity; + RLC_BearerConfig->servedRadioBearer->choice.drb_Identity = 1; + *RLC_BearerConfig->reestablishRLC = NR_RLC_BearerConfig__reestablishRLC_true; + +} + +void nr_rlc_bearer_init_ul_spec(struct NR_LogicalChannelConfig *mac_LogicalChannelConfig){ + + mac_LogicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*mac_LogicalChannelConfig->ul_SpecificParameters)); + mac_LogicalChannelConfig->ul_SpecificParameters->priority = 1; + mac_LogicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; + mac_LogicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; + mac_LogicalChannelConfig->ul_SpecificParameters->allowedServingCells = NULL; + mac_LogicalChannelConfig->ul_SpecificParameters->allowedSCS_List = NULL; + mac_LogicalChannelConfig->ul_SpecificParameters->maxPUSCH_Duration = NULL; + mac_LogicalChannelConfig->ul_SpecificParameters->configuredGrantType1Allowed = NULL; + + mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = calloc(1,sizeof(*mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup)); + *mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = 1; + mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = NULL; + mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = false; + mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = false; + mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL; + +} + +void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc_config_pr){ + + switch (rlc_config_pr){ + case NR_RLC_Config_PR_um_Bi_Directional: + // RLC UM Bi-directional Bearer configuration + rlc_Config->choice.um_Bi_Directional = calloc(1, sizeof(*rlc_Config->choice.um_Bi_Directional)); + rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength)); + *rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength)); + *rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; + rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + break; + case NR_RLC_Config_PR_am: + // RLC AM Bearer configuration + rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am)); + rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength)); + *rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; + rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45; + rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_p64; + rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_kB500; + rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t32; + rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(*rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength)); + *rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; + rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15; + rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15; + break; + default: + LOG_E (RLC, "Error in %s: RLC config type %d is not handled\n", __FUNCTION__, rlc_config_pr); + break; + } + + rlc_Config->present = rlc_config_pr; + +} + void mac_rlc_data_ind ( const module_id_t module_idP, const rnti_t rntiP, @@ -179,6 +250,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( + buf_stat.retx_size + buf_stat.tx_size; } else { + LOG_W(RLC, "[%s] Radio Bearer (channel ID %d) is NULL for UE with rntiP %x\n", __FUNCTION__, channel_idP, rntiP); ret.bytes_in_buffer = 0; } @@ -586,8 +658,7 @@ static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s) nr_rlc_manager_lock(nr_rlc_ue_manager); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); if (ue->srb[srb_id-1] != NULL) { - LOG_D(RLC, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n", - __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); + LOG_W(RLC, "%s:%d:%s: SRB %d already exists for UE with RNTI %x, do nothing\n", __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); } else { /* hack: hardcode values for NR */ t_poll_retransmit = 45; @@ -678,8 +749,7 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_ nr_rlc_manager_lock(nr_rlc_ue_manager); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); if (ue->drb[drb_id-1] != NULL) { - LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_W(RLC, "%s:%d:%s: DRB %d already exists for UE with RNTI %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { nr_rlc_am = new_nr_rlc_entity_am(100000, 100000, @@ -692,8 +762,7 @@ static void add_drb_am(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_ sn_field_length); nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_am); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added drb %d to UE with RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } nr_rlc_manager_unlock(nr_rlc_ue_manager); } @@ -752,8 +821,7 @@ static void add_drb_um(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_ nr_rlc_manager_lock(nr_rlc_ue_manager); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, rnti); if (ue->drb[drb_id-1] != NULL) { - LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_W(RLC, "DEBUG add_drb_um %s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } else { nr_rlc_um = new_nr_rlc_entity_um(1000000, 1000000, @@ -762,8 +830,7 @@ static void add_drb_um(int rnti, struct NR_DRB_ToAddMod *s, NR_RLC_BearerConfig_ sn_field_length); nr_rlc_ue_add_drb_rlc_entity(ue, drb_id, nr_rlc_um); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added drb %d to UE with RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } nr_rlc_manager_unlock(nr_rlc_ue_manager); } @@ -782,6 +849,7 @@ static void add_drb(int rnti, struct NR_DRB_ToAddMod *s, struct NR_RLC_BearerCon __FILE__, __LINE__, __FUNCTION__); exit(1); } + LOG_I(RLC, "%s:%s:%d: added DRB to UE with RNTI %x\n", __FILE__, __FUNCTION__, __LINE__, rnti); } /* Dummy function due to dependency from LTE libraries */ @@ -869,7 +937,7 @@ rlc_op_status_t rrc_rlc_config_req ( exit(1); } nr_rlc_manager_lock(nr_rlc_ue_manager); - LOG_D(RLC, "%s:%d:%s: remove rb %ld (is_srb %d) for UE %d\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP, ctxt_pP->rnti); + LOG_D(RLC, "%s:%d:%s: remove rb %ld (is_srb %d) for UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP, ctxt_pP->rnti); ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ctxt_pP->rnti); if (srb_flagP) { if (ue->srb[rb_idP-1] != NULL) { @@ -923,3 +991,13 @@ void nr_rlc_tick(int frame, int subframe) nr_rlc_current_time++; } } + +/* This is a hack, to compile the gNB. + * TODO: remove it. The solution is to cleanup cmake_targets/CMakeLists.txt + */ +void rlc_tick(int a, int b) +{ + LOG_E(RLC, "%s:%d:%s: this code should not be reached\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); +} diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h new file mode 100644 index 0000000000..26dee0590b --- /dev/null +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -0,0 +1,49 @@ +/* + * 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 nr_rlc_oai_api.h + * \brief Header file for nr_rlc_oai_api + * \author Guido Casati + * \date 2020 + * \email: guido.casati@iis.fraunhofe.de + * \version 1.0 + * @ingroup _rlc + + */ + +#include "NR_RLC-BearerConfig.h" +#include "NR_RLC-Config.h" +#include "NR_LogicalChannelIdentity.h" +#include "NR_RadioBearerConfig.h" +#include "NR_CellGroupConfig.h" +#include "openair2/RRC/NR/nr_rrc_proto.h" + +/* from OAI */ +#include "pdcp.h" + +struct NR_RLC_Config; +struct NR_LogicalChannelConfig; + +void nr_rlc_bearer_init(NR_RLC_BearerConfig_t *RLC_BearerConfig); + +void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc_config_pr); + +void nr_rlc_bearer_init_ul_spec(struct NR_LogicalChannelConfig *mac_LogicalChannelConfig); \ No newline at end of file diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c index d4db8d8484..8c46628333 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.c @@ -85,7 +85,7 @@ nr_rlc_ue_t *nr_rlc_manager_get_ue(nr_rlc_ue_manager_t *_m, int rnti) if (m->ue_list[i]->rnti == rnti) return m->ue_list[i]; - LOG_D(RLC, "%s:%d:%s: new UE %d\n", __FILE__, __LINE__, __FUNCTION__, rnti); + LOG_D(RLC, "%s:%d:%s: new UE with RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, rnti); m->ue_count++; m->ue_list = realloc(m->ue_list, sizeof(nr_rlc_ue_t *) * m->ue_count); diff --git a/openair2/LAYER2/rlc_v2/rlc_oai_api.c b/openair2/LAYER2/rlc_v2/rlc_oai_api.c index bd3eebe635..b3aaff742f 100644 --- a/openair2/LAYER2/rlc_v2/rlc_oai_api.c +++ b/openair2/LAYER2/rlc_v2/rlc_oai_api.c @@ -177,14 +177,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( mac_rlc_status_resp_t ret; rlc_entity_t *rb; - /* TODO: handle time a bit more properly */ - if (rlc_current_time_last_frame != frameP || - rlc_current_time_last_subframe != subframeP) { - rlc_current_time++; - rlc_current_time_last_frame = frameP; - rlc_current_time_last_subframe = subframeP; - } - rlc_manager_lock(rlc_ue_manager); ue = rlc_manager_get_ue(rlc_ue_manager, rntiP); @@ -244,14 +236,6 @@ rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( exit(1); } - /* TODO: handle time a bit more properly */ - if (rlc_current_time_last_frame != frameP || - rlc_current_time_last_subframe != subframeP) { - rlc_current_time++; - rlc_current_time_last_frame = frameP; - rlc_current_time_last_subframe = subframeP; - } - rlc_manager_lock(rlc_ue_manager); ue = rlc_manager_get_ue(rlc_ue_manager, rntiP); @@ -658,8 +642,7 @@ static void add_srb(int rnti, int module_id, struct LTE_SRB_ToAddMod *s) poll_pdu, poll_byte, max_retx_threshold); rlc_ue_add_srb_rlc_entity(ue, srb_id, rlc_am); - LOG_D(RLC, "%s:%d:%s: added srb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added SRB %d to UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); } rlc_manager_unlock(rlc_ue_manager); } @@ -736,8 +719,7 @@ static void add_drb_am(int rnti, int module_id, struct LTE_DRB_ToAddMod *s) poll_pdu, poll_byte, max_retx_threshold); rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_am); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added DRB %d to UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } rlc_manager_unlock(rlc_ue_manager); } @@ -807,8 +789,7 @@ static void add_drb_um(int rnti, int module_id, struct LTE_DRB_ToAddMod *s) sn_field_length); rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_um); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + LOG_D(RLC, "%s:%d:%s: added DRB %d to UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); } rlc_manager_unlock(rlc_ue_manager); } @@ -925,8 +906,7 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP ); rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_um); - LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", - __FILE__, __LINE__, __FUNCTION__, (int)drb_id, mbms_rnti); + LOG_D(RLC, "%s:%d:%s: added DRB %d to UE RNTI %x\n", __FILE__, __LINE__, __FUNCTION__, (int)drb_id, mbms_rnti); } rlc_manager_unlock(rlc_ue_manager); @@ -1028,3 +1008,27 @@ rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) return RLC_OP_STATUS_OK; } + +void rlc_tick(int frame, int subframe) +{ + int expected_next_frame; + int expected_next_subframe; + + if (frame != rlc_current_time_last_frame || + subframe != rlc_current_time_last_subframe) { + /* warn if discontinuity in ticks */ + expected_next_subframe = (rlc_current_time_last_subframe + 1) % 10; + if (expected_next_subframe == 0) + expected_next_frame = (rlc_current_time_last_frame + 1) % 1024; + else + expected_next_frame = rlc_current_time_last_frame; + if (expected_next_frame != frame || expected_next_subframe != subframe) + LOG_W(RLC, "rlc_tick: discontinuity (expected %d.%d, got %d.%d)\n", + expected_next_frame, expected_next_subframe, + frame, subframe); + + rlc_current_time++; + rlc_current_time_last_frame = frame; + rlc_current_time_last_subframe = subframe; + } +} diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 4e1a8ae131..7f98dd6a3e 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -30,12 +30,9 @@ * \warning */ -#include "openair1/PHY/defs_eNB.h" -#include "openair1/PHY/phy_extern.h" #include "openair1/SCHED_NR/fapi_nr_l1.h" #include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" #include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "common/ran_context.h" #include "executables/softmodem-common.h" @@ -79,35 +76,28 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } -void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, int target_snrx10) { - +void handle_nr_uci(NR_UL_IND_t *UL_info) +{ + const module_id_t mod_id = UL_info->module_id; + const frame_t frame = UL_info->frame; + const sub_frame_t slot = UL_info->slot; int num_ucis = UL_info->uci_ind.num_ucis; nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; for (int i = 0; i < num_ucis; i++) { switch (uci_list[i].pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: break; + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + LOG_E(MAC, "%s(): unhandled NFAPI_NR_UCI_PUSCH_PDU_TYPE\n", __func__); + break; case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; - - // tpc (power control) - sched_ctrl->tpc1 = nr_get_tpc(target_snrx10,uci_pdu->ul_cqi,30); - - if( (uci_pdu->pduBitmap>>1) & 0x01) - nr_rx_acknack(NULL,uci_pdu,NULL,UL_info,sched_ctrl,stats); - + const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; + handle_nr_uci_pucch_0_1(mod_id, frame, slot, uci_pdu); break; } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; - - // tpc (power control) - sched_ctrl->tpc1 = nr_get_tpc(target_snrx10,uci_pdu->ul_cqi,30); - - if( (uci_pdu->pduBitmap>>1) & 0x01) - nr_rx_acknack(NULL,NULL,uci_pdu,UL_info,sched_ctrl,stats); - + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4; + handle_nr_uci_pucch_2_3_4(mod_id, frame, slot, uci_pdu); break; } } @@ -117,75 +107,62 @@ void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_ } -void handle_nr_ulsch(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats) { +void handle_nr_ulsch(NR_UL_IND_t *UL_info) +{ + if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) { + for (int i = 0; i < UL_info->rx_ind.number_of_pdus; i++) { + for (int j = 0; j < UL_info->crc_ind.number_crcs; j++) { + // find crc_indication j corresponding rx_indication i + const nfapi_nr_rx_data_pdu_t *rx = &UL_info->rx_ind.pdu_list[i]; + const nfapi_nr_crc_t *crc = &UL_info->crc_ind.crc_list[j]; + LOG_D(PHY, + "UL_info->crc_ind.pdu_list[%d].rnti:%04x " + "UL_info->rx_ind.pdu_list[%d].rnti:%04x\n", + j, + crc->rnti, + i, + rx->rnti); - if(nfapi_mode == 1) { - if (UL_info->crc_ind.number_crcs>0) { - //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf)); - // oai_nfapi_crc_indication(&UL_info->crc_ind); + if (crc->rnti != rx->rnti) + continue; - UL_info->crc_ind.number_crcs = 0; - } + LOG_D(MAC, + "%4d.%2d Calling rx_sdu (CRC %s/tb_crc_status %d)\n", + UL_info->frame, + UL_info->slot, + crc->tb_crc_status ? "error" : "ok", + crc->tb_crc_status); - if (UL_info->rx_ind.number_of_pdus>0) { - //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf)); - // oai_nfapi_rx_ind(&UL_info->rx_ind); - UL_info->rx_ind.number_of_pdus = 0; - } - } else { + /* if CRC passes, pass PDU, otherwise pass NULL as error indication */ + nr_rx_sdu(UL_info->module_id, + UL_info->CC_id, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + rx->rnti, + crc->tb_crc_status ? NULL : rx->pdu, + rx->pdu_length, + rx->timing_advance, + rx->ul_cqi, + rx->rssi); + handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); + break; + } // for (j=0;jcrc_ind.number_crcs;j++) + } // for (i=0;irx_ind.number_of_pdus;i++) - if (UL_info->rx_ind.number_of_pdus>0 && UL_info->crc_ind.number_crcs>0) { - for (int i=0; irx_ind.number_of_pdus; i++) { - for (int j=0; jcrc_ind.number_crcs; j++) { - // find crc_indication j corresponding rx_indication i - LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].rx_ue_information.rnti:%04x UL_info->rx_ind.rx_indication_body.rx_pdu_list[%d].rx_ue_information.rnti:%04x\n", j, - UL_info->crc_ind.crc_list[j].rnti, i, UL_info->rx_ind.pdu_list[i].rnti); - - if (UL_info->crc_ind.crc_list[j].rnti == - UL_info->rx_ind.pdu_list[i].rnti) { - LOG_D(PHY, "UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].crc_indication_rel8.crc_flag:%d\n", j, UL_info->crc_ind.crc_list[j].tb_crc_status); - - handle_nr_ul_harq(UL_info->slot, sched_ctrl, stats, UL_info->crc_ind.crc_list[j]); - - if (UL_info->crc_ind.crc_list[j].tb_crc_status == 1) { // CRC error indication - LOG_D(MAC,"Frame %d, Slot %d Calling rx_sdu (CRC error) \n",UL_info->frame,UL_info->slot); - - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, //UL_info->frame, - UL_info->rx_ind.slot, //UL_info->slot, - UL_info->rx_ind.pdu_list[i].rnti, - (uint8_t *)NULL, - UL_info->rx_ind.pdu_list[i].pdu_length, - UL_info->rx_ind.pdu_list[i].timing_advance, - UL_info->rx_ind.pdu_list[i].ul_cqi, - UL_info->rx_ind.pdu_list[i].rssi); - } else { - LOG_D(MAC,"Frame %d, Slot %d Calling rx_sdu (CRC ok) \n",UL_info->frame,UL_info->slot); - nr_rx_sdu(UL_info->module_id, - UL_info->CC_id, - UL_info->rx_ind.sfn, //UL_info->frame, - UL_info->rx_ind.slot, //UL_info->slot, - UL_info->rx_ind.pdu_list[i].rnti, - UL_info->rx_ind.pdu_list[i].pdu, - UL_info->rx_ind.pdu_list[i].pdu_length, - UL_info->rx_ind.pdu_list[i].timing_advance, - UL_info->rx_ind.pdu_list[i].ul_cqi, - UL_info->rx_ind.pdu_list[i].rssi); - } - break; - } - } // for (j=0;jcrc_ind.number_crcs;j++) - } // for (i=0;irx_ind.number_of_pdus;i++) - - UL_info->crc_ind.number_crcs=0; - UL_info->rx_ind.number_of_pdus = 0; - } - else if (UL_info->rx_ind.number_of_pdus!=0 || UL_info->crc_ind.number_crcs!=0) { - LOG_E(PHY,"hoping not to have mis-match between CRC ind and RX ind - hopefully the missing message is coming shortly rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n", - UL_info->rx_ind.number_of_pdus, UL_info->rx_ind.sfn, UL_info->rx_ind.slot, - UL_info->crc_ind.number_crcs, UL_info->rx_ind.sfn, UL_info->rx_ind.slot); - } + UL_info->crc_ind.number_crcs = 0; + UL_info->rx_ind.number_of_pdus = 0; + } else if (UL_info->rx_ind.number_of_pdus != 0 + || UL_info->crc_ind.number_crcs != 0) { + LOG_E(PHY, + "hoping not to have mis-match between CRC ind and RX ind - " + "hopefully the missing message is coming shortly " + "rx_ind:%d(SFN/SL:%d/%d) crc_ind:%d(SFN/SL:%d/%d) \n", + UL_info->rx_ind.number_of_pdus, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot, + UL_info->crc_ind.number_crcs, + UL_info->rx_ind.sfn, + UL_info->rx_ind.slot); } } @@ -216,14 +193,12 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { ifi->CC_mask |= (1<frame,UL_info->slot); handle_nr_rach(UL_info); - handle_nr_uci(UL_info,&mac->UE_info.UE_sched_ctrl[0],&mac->UE_info.mac_stats[0],mac->pucch_target_snrx10); + handle_nr_uci(UL_info); // clear HI prior to handling ULSCH mac->UL_dci_req[CC_id].numPdus = 0; - handle_nr_ulsch(UL_info, &mac->UE_info.UE_sched_ctrl[0],&mac->UE_info.mac_stats[0]); + handle_nr_ulsch(UL_info); if (nfapi_mode != 1) { if (ifi->CC_mask == ((1<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->UL_tti_req = mac->UL_tti_req[CC_id]; sched_info->TX_req = &mac->TX_req[CC_id]; #ifdef DUMP_FAPI diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 5de9e96d85..349ad7c70c 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -69,6 +69,7 @@ #include "NR_RRCReconfigurationComplete.h" #include "NR_RRCReconfigurationComplete-IEs.h" #include "NR_DLInformationTransfer.h" +#include "NR_RRCReestablishmentRequest.h" #if defined(NR_Rel16) #include "NR_SCS-SpecificCarrier.h" #include "NR_TDD-UL-DL-ConfigCommon.h" @@ -652,7 +653,7 @@ uint8_t do_RRCSetup(const protocol_ctxt_t *const ctxt_pP, int CC_id, uint8_t *const buffer, const uint8_t transaction_id, - NR_SRB_ToAddModList_t *SRB_configList) + NR_SRB_ToAddModList_t **SRB_configList) //------------------------------------------------------------------------------ { asn_enc_rval_t enc_rval;; @@ -684,19 +685,19 @@ uint8_t do_RRCSetup(const protocol_ctxt_t *const ctxt_pP, /****************************** radioBearerConfig ******************************/ /* Configure SRB1 */ - if (SRB_configList) { - free(SRB_configList); + if (*SRB_configList) { + free(*SRB_configList); } - SRB_configList = calloc(1, sizeof(NR_SRB_ToAddModList_t)); + *SRB_configList = calloc(1, sizeof(NR_SRB_ToAddModList_t)); // SRB1 /* TODO */ SRB1_config = calloc(1, sizeof(NR_SRB_ToAddMod_t)); SRB1_config->srb_Identity = 1; // pdcp_Config->t_Reordering SRB1_config->pdcp_Config = pdcp_Config; - ie->radioBearerConfig.srb_ToAddModList = SRB_configList; - ASN_SEQUENCE_ADD(&SRB_configList->list, SRB1_config); + ie->radioBearerConfig.srb_ToAddModList = *SRB_configList; + ASN_SEQUENCE_ADD(&(*SRB_configList)->list, SRB1_config); ie->radioBearerConfig.srb3_ToRelease = NULL; ie->radioBearerConfig.drb_ToAddModList = NULL; @@ -954,26 +955,25 @@ uint8_t do_NR_RRCRelease(uint8_t *buffer, return((enc_rval.encoded+7)/8); } +//------------------------------------------------------------------------------ uint16_t do_RRCReconfiguration( const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP, uint8_t *buffer, - uint8_t Transaction_id, - gNB_RRC_INST *gnb_rrc_inst -) + uint8_t Transaction_id, + NR_SRB_ToAddModList_t *SRB_configList, + NR_DRB_ToAddModList_t *DRB_configList, + NR_DRB_ToReleaseList_t *DRB_releaseList, + NR_SecurityConfig_t *security_config, + NR_SDAP_Config_t *sdap_config, + NR_MeasConfig_t *meas_config, + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList + *dedicatedNAS_MessageList, + NR_MAC_CellGroupConfig_t *mac_CellGroupConfig) +//------------------------------------------------------------------------------ { NR_DL_DCCH_Message_t dl_dcch_msg; asn_enc_rval_t enc_rval; NR_RRCReconfiguration_IEs_t *ie; - NR_SRB_ToAddModList_t *SRB_configList = NULL; - NR_SRB_ToAddModList_t *SRB_configList2 = NULL; - NR_SRB_ToAddMod_t *SRB2_config = NULL; - NR_DRB_ToAddModList_t *DRB_configList = NULL; - NR_DRB_ToAddModList_t *DRB_configList2 = NULL; - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_SDAP_Config_t *sdap_config = NULL; - NR_SecurityConfig_t *security_config = NULL; - NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; memset(&dl_dcch_msg, 0, sizeof(NR_DL_DCCH_Message_t)); dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; @@ -985,73 +985,6 @@ uint16_t do_RRCReconfiguration( dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; /******************** Radio Bearer Config ********************/ - /* Configure SRB2 */ - SRB_configList2 = ue_context_pP->ue_context.SRB_configList2[Transaction_id]; - SRB_configList = ue_context_pP->ue_context.SRB_configList; - SRB_configList = CALLOC(1, sizeof(*SRB_configList)); - memset(SRB_configList, 0, sizeof(*SRB_configList)); - - if (SRB_configList2) { - free(SRB_configList2); - } - - SRB_configList2 = CALLOC(1, sizeof(*SRB_configList2)); - memset(SRB_configList2, 0, sizeof(*SRB_configList2)); - SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - SRB2_config->srb_Identity = 2; - ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); - ASN_SEQUENCE_ADD(&SRB_configList2->list, SRB2_config); - - /* Configure DRB */ - DRB_configList = ue_context_pP->ue_context.DRB_configList; - if (DRB_configList) { - free(DRB_configList); - } - - DRB_configList = CALLOC(1, sizeof(*DRB_configList)); - memset(DRB_configList, 0, sizeof(*DRB_configList)); - - DRB_configList2 = ue_context_pP->ue_context.DRB_configList2[Transaction_id]; - if (DRB_configList2) { - free(DRB_configList2); - } - DRB_configList2 = CALLOC(1, sizeof(*DRB_configList2)); - memset(DRB_configList2, 0, sizeof(*DRB_configList2)); - - DRB_config = CALLOC(1, sizeof(*DRB_config)); - DRB_config->drb_Identity = 1; - DRB_config->cnAssociation = CALLOC(1, sizeof(*DRB_config->cnAssociation)); - DRB_config->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; - // TODO sdap_Config - sdap_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); - memset(sdap_config, 0, sizeof(NR_SDAP_Config_t)); - DRB_config->cnAssociation->choice.sdap_Config = sdap_config; - // TODO pdcp_Config - DRB_config->reestablishPDCP = NULL; - DRB_config->recoverPDCP = NULL; - DRB_config->pdcp_Config = calloc(1, sizeof(*DRB_config->pdcp_Config)); - DRB_config->pdcp_Config->drb = calloc(1,sizeof(*DRB_config->pdcp_Config->drb)); - DRB_config->pdcp_Config->drb->discardTimer = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->discardTimer)); - *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_ms30; - DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL)); - *DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; - DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL)); - *DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; - DRB_config->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - DRB_config->pdcp_Config->drb->headerCompression.choice.notUsed = 0; - - DRB_config->pdcp_Config->drb->integrityProtection = NULL; - DRB_config->pdcp_Config->drb->statusReportRequired = NULL; - DRB_config->pdcp_Config->drb->outOfOrderDelivery = NULL; - DRB_config->pdcp_Config->moreThanOneRLC = NULL; - - DRB_config->pdcp_Config->t_Reordering = calloc(1, sizeof(*DRB_config->pdcp_Config->t_Reordering)); - *DRB_config->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0; - DRB_config->pdcp_Config->ext1 = NULL; - - ASN_SEQUENCE_ADD(&DRB_configList->list, DRB_config); - ASN_SEQUENCE_ADD(&DRB_configList2->list, DRB_config); - /* Configure Security */ // security_config = CALLOC(1, sizeof(NR_SecurityConfig_t)); // security_config->securityAlgorithmConfig = CALLOC(1, sizeof(*ie->radioBearerConfig->securityConfig->securityAlgorithmConfig)); @@ -1066,7 +999,7 @@ uint16_t do_RRCReconfiguration( ie->radioBearerConfig->drb_ToAddModList = DRB_configList; ie->radioBearerConfig->securityConfig = security_config; ie->radioBearerConfig->srb3_ToRelease = NULL; - ie->radioBearerConfig->drb_ToReleaseList = NULL; + ie->radioBearerConfig->drb_ToReleaseList = DRB_releaseList; /******************** Secondary Cell Group ********************/ // rrc_gNB_carrier_data_t *carrier = &(gnb_rrc_inst->carrier); @@ -1079,16 +1012,12 @@ uint16_t do_RRCReconfiguration( /******************** Meas Config ********************/ // measConfig - ie->measConfig = NULL; + ie->measConfig = meas_config; // lateNonCriticalExtension ie->lateNonCriticalExtension = NULL; // nonCriticalExtension ie->nonCriticalExtension = calloc(1, sizeof(NR_RRCReconfiguration_v1530_IEs_t)); - dedicatedNAS_Message = calloc(1, sizeof(NR_DedicatedNAS_Message_t)); - dedicatedNAS_Message->buf = ue_context_pP->ue_context.nas_pdu.buffer; - dedicatedNAS_Message->size = ue_context_pP->ue_context.nas_pdu.length; - ie->nonCriticalExtension->dedicatedNAS_MessageList = calloc(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); - ASN_SEQUENCE_ADD(&ie->nonCriticalExtension->dedicatedNAS_MessageList->list, dedicatedNAS_Message); + ie->nonCriticalExtension->dedicatedNAS_MessageList = dedicatedNAS_MessageList; dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration = ie; @@ -1264,10 +1193,6 @@ LOG_D(NR_RRC,"RRCSetupComplete Encoded %zd bits (%zd bytes)\n",enc_rval.encoded, return((enc_rval.encoded+7)/8); } -int do_DLInformationTransfer_NR (void * p) { - return 0; -} - //------------------------------------------------------------------------------ uint8_t do_NR_DLInformationTransfer( @@ -1329,3 +1254,202 @@ uint8_t do_NR_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8 return encoded; } + +uint8_t do_RRCReestablishmentRequest(uint8_t Mod_id, uint8_t *buffer, uint16_t c_rnti) { + asn_enc_rval_t enc_rval; + NR_UL_CCCH_Message_t ul_ccch_msg; + NR_RRCReestablishmentRequest_t *rrcReestablishmentRequest; + uint8_t buf[2]; + + memset((void *)&ul_ccch_msg,0,sizeof(NR_UL_CCCH_Message_t)); + ul_ccch_msg.message.present = NR_UL_CCCH_MessageType_PR_c1; + ul_ccch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_CCCH_MessageType__c1)); + ul_ccch_msg.message.choice.c1->present = NR_UL_CCCH_MessageType__c1_PR_rrcReestablishmentRequest; + ul_ccch_msg.message.choice.c1->choice.rrcReestablishmentRequest = CALLOC(1, sizeof(NR_RRCReestablishmentRequest_t)); + + rrcReestablishmentRequest = ul_ccch_msg.message.choice.c1->choice.rrcReestablishmentRequest; + // test + rrcReestablishmentRequest->rrcReestablishmentRequest.reestablishmentCause = NR_ReestablishmentCause_reconfigurationFailure; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.c_RNTI = c_rnti; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.physCellId = 0; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf = buf; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[0] = 0x08; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[1] = 0x32; + rrcReestablishmentRequest->rrcReestablishmentRequest.ue_Identity.shortMAC_I.size = 2; + + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_CCCH_Message, (void *)&ul_ccch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_CCCH_Message, + NULL, + (void *)&ul_ccch_msg, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + LOG_D(NR_RRC,"[UE] RRCReestablishmentRequest Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); +} + +//------------------------------------------------------------------------------ +uint8_t +do_RRCReestablishment( +const protocol_ctxt_t *const ctxt_pP, +rrc_gNB_ue_context_t *const ue_context_pP, +int CC_id, +uint8_t *const buffer, +//const uint8_t transmission_mode, +const uint8_t Transaction_id, +NR_SRB_ToAddModList_t **SRB_configList +) { + asn_enc_rval_t enc_rval; + //long *logicalchannelgroup = NULL; + struct NR_SRB_ToAddMod *SRB1_config = NULL; + struct NR_SRB_ToAddMod *SRB2_config = NULL; + //gNB_RRC_INST *nrrrc = RC.nrrrc[ctxt_pP->module_id]; + NR_DL_DCCH_Message_t dl_dcch_msg; + NR_RRCReestablishment_t *rrcReestablishment = NULL; + int i = 0; + ue_context_pP->ue_context.reestablishment_xid = Transaction_id; + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[Transaction_id]; + + if (*SRB_configList2) { + free(*SRB_configList2); + } + + *SRB_configList2 = CALLOC(1, sizeof(NR_SRB_ToAddModList_t)); + memset((void *)&dl_dcch_msg, 0, sizeof(NR_DL_DCCH_Message_t)); + dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; + dl_dcch_msg.message.choice.c1 = calloc(1,sizeof(struct NR_DL_DCCH_MessageType__c1)); + dl_dcch_msg.message.choice.c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment; + dl_dcch_msg.message.choice.c1->choice.rrcReestablishment = CALLOC(1,sizeof(NR_RRCReestablishment_t)); + rrcReestablishment = dl_dcch_msg.message.choice.c1->choice.rrcReestablishment; + + // get old configuration of SRB2 + if (*SRB_configList != NULL) { + for (i = 0; (i < (*SRB_configList)->list.count) && (i < 3); i++) { + LOG_D(NR_RRC, "(*SRB_configList)->list.array[%d]->srb_Identity=%ld\n", + i, (*SRB_configList)->list.array[i]->srb_Identity); + + if ((*SRB_configList)->list.array[i]->srb_Identity == 2 ) { + SRB2_config = (*SRB_configList)->list.array[i]; + } else if ((*SRB_configList)->list.array[i]->srb_Identity == 1 ) { + SRB1_config = (*SRB_configList)->list.array[i]; + } + } + } + + if (SRB1_config == NULL) { + // default SRB1 configuration + LOG_W(NR_RRC,"SRB1 configuration does not exist in SRB configuration list, use default\n"); + /// SRB1 + SRB1_config = CALLOC(1, sizeof(*SRB1_config)); + SRB1_config->srb_Identity = 1; + } + + if (SRB2_config == NULL) { + LOG_W(NR_RRC,"SRB2 configuration does not exist in SRB configuration list\n"); + } else { + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); + } + + if (*SRB_configList) { + free(*SRB_configList); + } + + *SRB_configList = CALLOC(1, sizeof(LTE_SRB_ToAddModList_t)); + ASN_SEQUENCE_ADD(&(*SRB_configList)->list,SRB1_config); + + rrcReestablishment->rrc_TransactionIdentifier = Transaction_id; + rrcReestablishment->criticalExtensions.present = NR_RRCReestablishment__criticalExtensions_PR_rrcReestablishment; + rrcReestablishment->criticalExtensions.choice.rrcReestablishment = CALLOC(1,sizeof(NR_RRCReestablishment_IEs_t)); + + uint8_t KgNB_star[32] = { 0 }; + /** TODO + uint16_t pci = nrrrc->carrier[CC_id].physCellId; + uint32_t earfcn_dl = (uint32_t)freq_to_arfcn10(RC.mac[ctxt_pP->module_id]->common_channels[CC_id].eutra_band, + nrrrc->carrier[CC_id].dl_CarrierFreq); + bool is_rel8_only = true; + + if (earfcn_dl > 65535) { + is_rel8_only = false; + } + LOG_D(NR_RRC, "pci=%d, eutra_band=%d, downlink_frequency=%d, earfcn_dl=%u, is_rel8_only=%s\n", + pci, + RC.mac[ctxt_pP->module_id]->common_channels[CC_id].eutra_band, + nrrrc->carrier[CC_id].dl_CarrierFreq, + earfcn_dl, + is_rel8_only == true ? "true": "false"); + */ + + if (ue_context_pP->ue_context.nh_ncc >= 0) { + //TODO derive_keNB_star(ue_context_pP->ue_context.nh, pci, earfcn_dl, is_rel8_only, KgNB_star); + rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount = ue_context_pP->ue_context.nh_ncc; + } else { // first HO + //TODO derive_keNB_star (ue_context_pP->ue_context.kgnb, pci, earfcn_dl, is_rel8_only, KgNB_star); + // LG: really 1 + rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount = 0; + } + // copy KgNB_star to ue_context_pP->ue_context.kgnb + memcpy (ue_context_pP->ue_context.kgnb, KgNB_star, 32); + ue_context_pP->ue_context.kgnb_ncc = 0; + rrcReestablishment->criticalExtensions.choice.rrcReestablishment->lateNonCriticalExtension = NULL; + rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nonCriticalExtension = NULL; + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message, + NULL, + (void *)&dl_dcch_msg, + buffer, + 100); + + if(enc_rval.encoded == -1) { + LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + return -1; + } + + LOG_D(NR_RRC,"RRCReestablishment Encoded %u bits (%u bytes)\n", + (uint32_t)enc_rval.encoded, (uint32_t)(enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); + +} + +uint8_t +do_RRCReestablishmentComplete(uint8_t *buffer, int64_t rrc_TransactionIdentifier) { + asn_enc_rval_t enc_rval; + NR_UL_DCCH_Message_t ul_dcch_msg; + NR_RRCReestablishmentComplete_t *rrcReestablishmentComplete; + + memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; + ul_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_UL_DCCH_MessageType__c1)); + ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_rrcReestablishmentComplete; + ul_dcch_msg.message.choice.c1->choice.rrcReestablishmentComplete = CALLOC(1, sizeof(NR_RRCReestablishmentComplete_t)); + + rrcReestablishmentComplete = ul_dcch_msg.message.choice.c1->choice.rrcReestablishmentComplete; + rrcReestablishmentComplete->rrc_TransactionIdentifier = rrc_TransactionIdentifier; + rrcReestablishmentComplete->criticalExtensions.present = NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete; + rrcReestablishmentComplete->criticalExtensions.choice.rrcReestablishmentComplete = CALLOC(1, sizeof(NR_RRCReestablishmentComplete_IEs_t)); + rrcReestablishmentComplete->criticalExtensions.choice.rrcReestablishmentComplete->lateNonCriticalExtension = NULL; + rrcReestablishmentComplete->criticalExtensions.choice.rrcReestablishmentComplete->nonCriticalExtension = NULL; + + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_CCCH_Message, (void *)&ul_dcch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, + NULL, + (void *)&ul_dcch_msg, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); + LOG_D(NR_RRC,"[UE] RRCReestablishmentComplete Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); +} + diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 44947c04ed..bfc4942138 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -91,7 +91,7 @@ uint8_t do_RRCSetup(const protocol_ctxt_t *const ctxt_pP, int CC_id, uint8_t *const buffer, const uint8_t transaction_id, - NR_SRB_ToAddModList_t *SRB_configList); + NR_SRB_ToAddModList_t **SRB_configList); uint8_t do_NR_SecurityModeCommand( const protocol_ctxt_t *const ctxt_pP, uint8_t *const buffer, @@ -106,11 +106,18 @@ uint8_t do_NR_SA_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, uint8_t do_NR_RRCRelease(uint8_t *buffer, uint8_t Transaction_id); uint16_t do_RRCReconfiguration( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP, - uint8_t *buffer, - uint8_t Transaction_id, - gNB_RRC_INST *gnb_rrc_inst); + const protocol_ctxt_t *const ctxt_pP, + uint8_t *buffer, + uint8_t Transaction_id, + NR_SRB_ToAddModList_t *SRB_configList, + NR_DRB_ToAddModList_t *DRB_configList, + NR_DRB_ToReleaseList_t *DRB_releaseList, + NR_SecurityConfig_t *security_config, + NR_SDAP_Config_t *sdap_config, + NR_MeasConfig_t *meas_config, + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList + *dedicatedNAS_MessageList, + NR_MAC_CellGroupConfig_t *mac_CellGroupConfig); uint8_t do_RRCSetupComplete(uint8_t Mod_id, uint8_t *buffer, @@ -138,4 +145,23 @@ do_NR_DLInformationTransfer( uint8_t do_NR_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, - uint8_t *pdu_buffer); \ No newline at end of file + uint8_t *pdu_buffer); + +uint8_t do_RRCReestablishmentRequest(uint8_t Mod_id, uint8_t *buffer, uint16_t c_rnti); + +uint8_t +do_RRCReestablishment( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + int CC_id, + uint8_t *const buffer, + //const uint8_t transmission_mode, + const uint8_t Transaction_id, + NR_SRB_ToAddModList_t **SRB_configList +); + +uint8_t +do_RRCReestablishmentComplete( + uint8_t *buffer, + int64_t rrc_TransactionIdentifier); + diff --git a/openair2/RRC/NR/nr_ngap_gNB.c b/openair2/RRC/NR/nr_ngap_gNB.c index 0d4892bb88..88c0762c99 100644 --- a/openair2/RRC/NR/nr_ngap_gNB.c +++ b/openair2/RRC/NR/nr_ngap_gNB.c @@ -47,7 +47,7 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(void ) { rrc_gNB_process_NGAP_DOWNLINK_NAS(); } -void nr_rrc_rx_tx() { +void nr_rrc_rx_tx(void) { // check timers // check if UEs are lost, to remove them from upper layers diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index ec73b0633e..17a6c86999 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -261,7 +261,10 @@ typedef enum pdu_session_satus_e { PDU_SESSION_STATUS_NEW, PDU_SESSION_STATUS_DONE, PDU_SESSION_STATUS_ESTABLISHED, + PDU_SESSION_STATUS_REESTABLISHED, // after HO + PDU_SESSION_STATUS_TOMODIFY, // ENDC NSA PDU_SESSION_STATUS_FAILED, + PDU_SESSION_STATUS_TORELEASE // to release DRB between eNB and UE } pdu_session_status_t; typedef struct pdu_session_param_s { @@ -323,7 +326,7 @@ typedef struct gNB_RRC_UE_s { NR_EstablishmentCause_t establishment_cause; /* Information from UE RRC ConnectionReestablishmentRequest */ - NR_ReestablishmentCause_t reestablishment_cause; + NR_ReestablishmentCause_t reestablishment_cause; /* UE id for initial connection to S1AP */ uint16_t ue_initial_id; @@ -349,10 +352,14 @@ typedef struct gNB_RRC_UE_s { uint8_t nb_of_failed_e_rabs; e_rab_param_t modify_e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; /* list of e_rab to be setup by RRC layers */ + /* list of pdu session to be setup by RRC layers */ + e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; pdu_session_param_t pdusession[NR_NB_RB_MAX];//[NGAP_MAX_PDU_SESSION]; //release e_rabs uint8_t nb_release_of_e_rabs; e_rab_failed_t e_rabs_release_failed[S1AP_MAX_E_RAB]; + uint8_t nb_release_of_pdusessions; + pdusession_failed_t pdusessions_release_failed[NGAP_MAX_PDUSESSION]; // LG: For GTPV1 TUNNELS uint32_t gnb_gtp_teid[S1AP_MAX_E_RAB]; transport_layer_addr_t gnb_gtp_addrs[S1AP_MAX_E_RAB]; @@ -371,6 +378,9 @@ typedef struct gNB_RRC_UE_s { uint32_t ue_reestablishment_timer; uint32_t ue_reestablishment_timer_thres; uint8_t e_rab_release_command_flag; + uint8_t pdu_session_release_command_flag; + uint32_t ue_rrc_inactivity_timer; + int8_t reestablishment_xid; //------------------------------------------------------------------------------// NR_CellGroupId_t cellGroupId; struct NR_SpCellConfig *spCellConfig; @@ -429,6 +439,8 @@ typedef struct { NR_SRB_INFO SI; NR_SRB_INFO Srb0; int initial_csi_index[MAX_NR_RRC_UE_CONTEXTS]; + int physCellId; + int p_gNB; } rrc_gNB_carrier_data_t; //--------------------------------------------------- diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 432883ae88..80812a7df4 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -123,6 +123,14 @@ void *rrc_gnb_task(void *args_p); /* Trigger RRC periodic processing. To be called once per ms. */ void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe); +/**\ Function to set or overwrite PTRS DL RRC parameters. + \ *bwp Pointer to dedicated RC config structure + \ *ptrsNrb Pointer to K_ptrs N_RB related parameters + \ *ptrsMcs Pointer to L_ptrs MCS related parameters + \ *epre_Ratio Pointer to ep_ratio + \ *reOffset Pointer to RE Offset Value */ +void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset); + uint8_t nr_rrc_data_req( const protocol_ctxt_t *const ctxt_pP, @@ -138,3 +146,10 @@ int nr_rrc_mac_remove_ue(module_id_t mod_idP, rnti_t rntiP); +void +rrc_gNB_generate_dedicatedRRCReconfiguration_release( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid, + uint32_t nas_length, + uint8_t *nas_buffer); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 8a09359c65..31be11e85e 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -54,6 +54,8 @@ #include "NR_UL-CCCH-Message.h" #include "NR_RRCSetupRequest-IEs.h" #include "NR_RRCSetupComplete-IEs.h" +#include "NR_RRCReestablishmentRequest-IEs.h" +#include "NR_MIB.h" #include "rlc.h" #include "rrc_eNB_UE_context.h" @@ -75,7 +77,7 @@ #include "rrc_eNB_GTPV1U.h" - +#include "nr_pdcp/nr_pdcp_entity.h" #include "pdcp.h" #include "gtpv1u_eNB_task.h" @@ -119,6 +121,7 @@ extern rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * con static inline uint64_t bitStr_to_uint64(BIT_STRING_t *asn); mui_t rrc_gNB_mui = 0; +uint8_t first_rrcreconfiguration = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// @@ -360,8 +363,8 @@ rrc_gNB_generate_RRCSetup( //----------------------------------------------------------------------------- { LOG_I(NR_RRC, "rrc_gNB_generate_RRCSetup \n"); - NR_SRB_ToAddModList_t *SRB_configList = NULL; - MessageDef *message_p; + NR_SRB_ToAddModList_t **SRB_configList = NULL; + MessageDef *message_p; // T(T_GNB_RRC_SETUP, // T_INT(ctxt_pP->module_id), @@ -369,7 +372,7 @@ rrc_gNB_generate_RRCSetup( // T_INT(ctxt_pP->subframe), // T_INT(ctxt_pP->rnti)); gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - SRB_configList = ue_p->SRB_configList; + SRB_configList = &ue_p->SRB_configList; ue_p->Srb0.Tx_buffer.payload_size = do_RRCSetup(ctxt_pP, ue_context_pP, CC_id, @@ -409,12 +412,11 @@ rrc_gNB_generate_RRCSetup( { // rrc_mac_config_req_gNB #ifdef ITTI_SIM - MessageDef *message_p; uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB_SIM, TASK_RRC_UE_SIM, + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, ue_p->Srb0.Tx_buffer.payload_size); memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); - message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, GNB_RRC_CCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_CCCH_DATA_IND); GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); @@ -450,6 +452,82 @@ rrc_gNB_generate_RRCSetup( } } +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest( + const protocol_ctxt_t *const ctxt_pP, + const int CC_id +) +//----------------------------------------------------------------------------- +{ + LOG_I(NR_RRC, "generate RRCSetup for RRCReestablishmentRequest \n"); + NR_SRB_ToAddModList_t **SRB_configList = NULL; + rrc_gNB_ue_context_t *ue_context_pP = NULL; + gNB_RRC_INST *rrc_instance_p = RC.nrrrc[ctxt_pP->module_id]; + + ue_context_pP = rrc_gNB_get_next_free_ue_context(ctxt_pP, rrc_instance_p, 0); + + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + SRB_configList = &ue_p->SRB_configList; + ue_p->Srb0.Tx_buffer.payload_size = do_RRCSetup(ctxt_pP, + ue_context_pP, + CC_id, + (uint8_t *) ue_p->Srb0.Tx_buffer.Payload, + rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id), + SRB_configList); + + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, + (char *)(ue_p->Srb0.Tx_buffer.Payload), + ue_p->Srb0.Tx_buffer.payload_size, + "[MSG] RRC Setup\n"); + + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RRC_gNB --- MAC_CONFIG_REQ (SRB1) ---> MAC_gNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + + rrc_mac_config_req_gNB(rrc_instance_p->module_id, + rrc_instance_p->carrier.ssb_SubcarrierOffset, + rrc_instance_p->carrier.pdsch_AntennaPorts, + rrc_instance_p->carrier.pusch_TargetSNRx10, + rrc_instance_p->carrier.pucch_TargetSNRx10, + (NR_ServingCellConfigCommon_t *)rrc_instance_p->carrier.servingcellconfigcommon, + 0, + ue_context_pP->ue_context.rnti, + (NR_CellGroupConfig_t *)NULL + ); + + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + ue_p->Srb0.Tx_buffer.Header, // LG WARNING + ue_p->Srb0.Tx_buffer.payload_size, + MSC_AS_TIME_FMT" RRCSetup UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + ue_p->Srb0.Tx_buffer.payload_size); + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCSetup (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_p->Srb0.Tx_buffer.payload_size); + // activate release timer, if RRCSetupComplete not received after 100 frames, remove UE + ue_context_pP->ue_context.ue_release_timer = 1; + // remove UE after 10 frames after RRCConnectionRelease is triggered + ue_context_pP->ue_context.ue_release_timer_thres = 1000; + /* init timers */ + // ue_context_pP->ue_context.ue_rrc_inactivity_timer = 0; +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, + ue_p->Srb0.Tx_buffer.payload_size); + memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_CCCH_DATA_IND); + GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#endif +} + void rrc_gNB_generate_RRCReject( const protocol_ctxt_t *const ctxt_pP, @@ -460,7 +538,7 @@ rrc_gNB_generate_RRCReject( { LOG_I(NR_RRC, "rrc_gNB_generate_RRCReject \n"); gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - MessageDef *message_p; + MessageDef *message_p; ue_p->Srb0.Tx_buffer.payload_size = do_RRCReject(ctxt_pP->module_id, (uint8_t *)ue_p->Srb0.Tx_buffer.Payload); @@ -507,10 +585,10 @@ rrc_gNB_generate_RRCReject( { #ifdef ITTI_SIM uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB_SIM, TASK_RRC_UE_SIM, + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, ue_p->Srb0.Tx_buffer.payload_size); memcpy (message_buffer, (uint8_t*)ue_p->Srb0.Tx_buffer.Payload, ue_p->Srb0.Tx_buffer.payload_size); - message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, GNB_RRC_CCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_CCCH_DATA_IND); GNB_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_CCCH_DATA_IND (message_p).size = ue_p->Srb0.Tx_buffer.payload_size; itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); @@ -551,24 +629,121 @@ rrc_gNB_process_RRCSetupComplete( //----------------------------------------------------------------------------- void rrc_gNB_generate_defaultRRCReconfiguration( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *ue_context_pP + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP ) //----------------------------------------------------------------------------- { - // gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - uint8_t buffer[RRC_BUF_SIZE]; - uint16_t size; - gNB_RRC_INST *gnb_rrc_inst = RC.nrrrc[ctxt_pP->module_id]; - MessageDef *message_p; + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; + NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; + NR_DRB_ToAddModList_t **DRB_configList = NULL; + NR_DRB_ToAddModList_t **DRB_configList2 = NULL; + NR_SRB_ToAddMod_t *SRB2_config = NULL; + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_SDAP_Config_t *sdap_config = NULL; + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList + *dedicatedNAS_MessageList = NULL; + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; + MessageDef *message_p; - size = do_RRCReconfiguration(ctxt_pP, ue_context_pP, buffer, - rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id), - gnb_rrc_inst); - LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)buffer, size, "[MSG] RRC Reconfiguration\n"); + uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + + /******************** Radio Bearer Config ********************/ + /* Configure SRB2 */ + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; + if (*SRB_configList2) { + free(*SRB_configList2); + } + *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); + memset(*SRB_configList2, 0, sizeof(**SRB_configList2)); + SRB2_config = CALLOC(1, sizeof(*SRB2_config)); + SRB2_config->srb_Identity = 2; + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); + ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); + + /* Configure DRB */ + DRB_configList = &ue_context_pP->ue_context.DRB_configList; + if (*DRB_configList) { + free(*DRB_configList); + } + *DRB_configList = CALLOC(1, sizeof(**DRB_configList)); + memset(*DRB_configList, 0, sizeof(**DRB_configList)); + + DRB_configList2 = &ue_context_pP->ue_context.DRB_configList2[xid]; + if (*DRB_configList2) { + free(*DRB_configList2); + } + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); + memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); + + DRB_config = CALLOC(1, sizeof(*DRB_config)); + DRB_config->drb_Identity = 1; + DRB_config->cnAssociation = CALLOC(1, sizeof(*DRB_config->cnAssociation)); + DRB_config->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + // TODO sdap_Config + sdap_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); + memset(sdap_config, 0, sizeof(NR_SDAP_Config_t)); + DRB_config->cnAssociation->choice.sdap_Config = sdap_config; + // TODO pdcp_Config + DRB_config->reestablishPDCP = NULL; + DRB_config->recoverPDCP = NULL; + DRB_config->pdcp_Config = calloc(1, sizeof(*DRB_config->pdcp_Config)); + DRB_config->pdcp_Config->drb = calloc(1,sizeof(*DRB_config->pdcp_Config->drb)); + DRB_config->pdcp_Config->drb->discardTimer = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->discardTimer)); + *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_ms30; + DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL)); + *DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; + DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL)); + *DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; + DRB_config->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + DRB_config->pdcp_Config->drb->headerCompression.choice.notUsed = 0; + + DRB_config->pdcp_Config->drb->integrityProtection = NULL; + DRB_config->pdcp_Config->drb->statusReportRequired = NULL; + DRB_config->pdcp_Config->drb->outOfOrderDelivery = NULL; + DRB_config->pdcp_Config->moreThanOneRLC = NULL; + + DRB_config->pdcp_Config->t_Reordering = calloc(1, sizeof(*DRB_config->pdcp_Config->t_Reordering)); + *DRB_config->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0; + DRB_config->pdcp_Config->ext1 = NULL; + + ASN_SEQUENCE_ADD(&(*DRB_configList)->list, DRB_config); + ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); + + dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); + + if (ue_context_pP->ue_context.nas_pdu_flag == 1) { + dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); + memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedNAS_Message, + (char *)ue_context_pP->ue_context.nas_pdu.buffer, + ue_context_pP->ue_context.nas_pdu.length); + ASN_SEQUENCE_ADD(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); + } + + /* If list is empty free the list and reset the address */ + if (dedicatedNAS_MessageList->list.count == 0) { + free(dedicatedNAS_MessageList); + dedicatedNAS_MessageList = NULL; + } + + memset(buffer, 0, RRC_BUF_SIZE); + size = do_RRCReconfiguration(ctxt_pP, buffer, + xid, + *SRB_configList2, + *DRB_configList, + NULL, + NULL, + NULL, + NULL, + dedicatedNAS_MessageList, + NULL); free(ue_context_pP->ue_context.nas_pdu.buffer); + LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)buffer, size, "[MSG] RRC Reconfiguration\n"); LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE id %x)\n", ctxt_pP->module_id, ctxt_pP->frame, @@ -611,9 +786,9 @@ rrc_gNB_generate_defaultRRCReconfiguration( { #ifdef ITTI_SIM uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB_SIM, TASK_RRC_UE_SIM, size); + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); memcpy (message_buffer, buffer, size); - message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, GNB_RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_DCCH_DATA_IND); GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_DCCH_DATA_IND (message_p).size = size; @@ -656,6 +831,112 @@ rrc_gNB_generate_defaultRRCReconfiguration( } } +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_dedicatedRRCReconfiguration_release( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid, + uint32_t nas_length, + uint8_t *nas_buffer) +//----------------------------------------------------------------------------- +{ + uint8_t buffer[RRC_BUF_SIZE]; + int i; + uint16_t size = 0; + NR_DRB_ToReleaseList_t **DRB_Release_configList2 = NULL; + NR_DRB_Identity_t *DRB_release; + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList + *dedicatedNAS_MessageList = NULL; + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; + + DRB_Release_configList2 = &ue_context_pP->ue_context.DRB_Release_configList2[xid]; + if (*DRB_Release_configList2) { + free(*DRB_Release_configList2); + } + + *DRB_Release_configList2 = CALLOC(1, sizeof(**DRB_Release_configList2)); + for(i = 0; i < NB_RB_MAX; i++) { + if((ue_context_pP->ue_context.pdusession[i].status == PDU_SESSION_STATUS_TORELEASE) && ue_context_pP->ue_context.pdusession[i].xid == xid) { + DRB_release = CALLOC(1, sizeof(NR_DRB_Identity_t)); + *DRB_release = i+1; + ASN_SEQUENCE_ADD(&(*DRB_Release_configList2)->list, DRB_release); + } + } + + /* If list is empty free the list and reset the address */ + if (nas_length > 0) { + dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); + dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); + memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(dedicatedNAS_Message, + (char *)nas_buffer, + nas_length); + ASN_SEQUENCE_ADD(&dedicatedNAS_MessageList->list, dedicatedNAS_Message); + LOG_I(NR_RRC,"add NAS info with size %d\n", nas_length); + } else { + LOG_W(NR_RRC,"dedlicated NAS list is empty\n"); + } + + memset(buffer, 0, RRC_BUF_SIZE); + size = do_RRCReconfiguration(ctxt_pP, buffer, xid, + NULL, + NULL, + *DRB_Release_configList2, + NULL, + NULL, + NULL, + dedicatedNAS_MessageList, + NULL); + + ue_context_pP->ue_context.pdu_session_release_command_flag = 1; + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, + "[MSG] RRC Reconfiguration\n"); + + /* Free all NAS PDUs */ + if (nas_length > 0) { + /* Free the NAS PDU buffer and invalidate it */ + free(nas_buffer); + } + + LOG_I(NR_RRC, + "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE RNTI %x)\n", + ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); + LOG_D(NR_RRC, + "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_gNB_mui, ctxt_pP->module_id, DCCH); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" dedicated NR_RRCReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + nr_rrc_data_req( + ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif +} + //----------------------------------------------------------------------------- /* * Process the RRC Reconfiguration Complete from the UE @@ -675,7 +956,7 @@ rrc_gNB_process_RRCReconfigurationComplete( NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid]; NR_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid]; NR_DRB_Identity_t *drb_id_p = NULL; - uint8_t nr_DRB2LCHAN[8]; +// uint8_t nr_DRB2LCHAN[8]; ue_context_pP->ue_context.ue_reestablishment_timer = 0; @@ -750,12 +1031,12 @@ rrc_gNB_process_RRCReconfigurationComplete( for (int i = 0; i < DRB_configList->list.count; i++) { if (DRB_configList->list.array[i]) { drb_id = (int)DRB_configList->list.array[i]->drb_Identity; - LOG_I(NR_RRC, "[gNB %d] Frame %d : Logical Channel UL-DCCH, Received NR_RRCReconfigurationComplete from UE rnti %x, reconfiguring DRB %d/LCID %d\n", + LOG_I(NR_RRC, "[gNB %d] Frame %d : Logical Channel UL-DCCH, Received NR_RRCReconfigurationComplete from UE rnti %x, reconfiguring DRB %d\n", ctxt_pP->module_id, ctxt_pP->frame, ctxt_pP->rnti, - (int)DRB_configList->list.array[i]->drb_Identity, - (int)*DRB_configList->list.array[i]->pdcp_Config->moreThanOneRLC->primaryPath.logicalChannel); + (int)DRB_configList->list.array[i]->drb_Identity); + //(int)*DRB_configList->list.array[i]->pdcp_Config->moreThanOneRLC->primaryPath.logicalChannel); if (ue_context_pP->ue_context.DRB_active[drb_id] == 0) { ue_context_pP->ue_context.DRB_active[drb_id] = 1; @@ -766,9 +1047,9 @@ rrc_gNB_process_RRCReconfigurationComplete( PROTOCOL_NR_RRC_CTXT_UE_FMT" RRC_gNB --- MAC_CONFIG_REQ (DRB) ---> MAC_gNB\n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); - if (DRB_configList->list.array[i]->pdcp_Config->moreThanOneRLC->primaryPath.logicalChannel) { - nr_DRB2LCHAN[i] = (uint8_t) * DRB_configList->list.array[i]->pdcp_Config->moreThanOneRLC->primaryPath.logicalChannel; - } + //if (DRB_configList->list.array[i]->pdcp_Config->moreThanOneRLC->primaryPath.logicalChannel) { + // nr_DRB2LCHAN[i] = (uint8_t) * DRB_configList->list.array[i]->pdcp_Config->moreThanOneRLC->primaryPath.logicalChannel; + //} // rrc_mac_config_req_eNB } else { // remove LCHAN from MAC/PHY @@ -777,12 +1058,12 @@ rrc_gNB_process_RRCReconfigurationComplete( /* rrc_pdcp_config_req (ctxt_pP->module_id, frameP, 1, CONFIG_ACTION_REMOVE, (ue_mod_idP * NB_RB_MAX) + DRB2LCHAN[i],UNDEF_SECURITY_MODE); */ - rrc_rlc_config_req(ctxt_pP, + /*rrc_rlc_config_req(ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, CONFIG_ACTION_REMOVE, nr_DRB2LCHAN[i], - Rlc_info_um); + Rlc_info_um);*/ } ue_context_pP->ue_context.DRB_active[drb_id] = 0; @@ -815,6 +1096,350 @@ rrc_gNB_process_RRCReconfigurationComplete( ue_context_pP->ue_context.DRB_Release_configList2[xid] = NULL; } } + +//----------------------------------------------------------------------------- +void +rrc_gNB_generate_RRCReestablishment( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + const int CC_id) +//----------------------------------------------------------------------------- +{ + // int UE_id = -1; + //NR_LogicalChannelConfig_t *SRB1_logicalChannelConfig = NULL; + NR_SRB_ToAddModList_t **SRB_configList; + // NR_SRB_ToAddMod_t *SRB1_config = NULL; + //rrc_gNB_carrier_data_t *carrier = NULL; + gNB_RRC_UE_t *ue_context = NULL; + module_id_t module_id = ctxt_pP->module_id; + // uint16_t rnti = ctxt_pP->rnti; + + SRB_configList = &(ue_context_pP->ue_context.SRB_configList); + //carrier = &(RC.nrrrc[ctxt_pP->module_id]->carrier); + ue_context = &(ue_context_pP->ue_context); + ue_context->Srb0.Tx_buffer.payload_size = do_RRCReestablishment(ctxt_pP, + ue_context_pP, + CC_id, + (uint8_t *) ue_context->Srb0.Tx_buffer.Payload, + //(uint8_t) carrier->p_gNB, // at this point we do not have the UE capability information, so it can only be TM1 or TM2 + rrc_gNB_get_next_transaction_identifier(module_id), + SRB_configList + //&(ue_context->physicalConfigDedicated) + ); + + /* Configure SRB1 for UE */ + if (*SRB_configList != NULL) { + for (int cnt = 0; cnt < (*SRB_configList)->list.count; cnt++) { + if ((*SRB_configList)->list.array[cnt]->srb_Identity == 1) { + // SRB1_config = (*SRB_configList)->list.array[cnt]; + } + + LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" RRC_gNB --- MAC_CONFIG_REQ (SRB1) ---> MAC_gNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + + // rrc_mac_config_req_eNB + } + } // if (*SRB_configList != NULL) + + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, + MSC_RRC_UE, + ue_context->Srb0.Tx_buffer.Header, + ue_context->Srb0.Tx_buffer.payload_size, + MSC_AS_TIME_FMT" NR_RRCReestablishment UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context->rnti, + ue_context->Srb0.Tx_buffer.payload_size); + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context->Srb0.Tx_buffer.payload_size); +#if(0) + UE_id = find_nr_UE_id(module_id, rnti); + if (UE_id != -1) { + /* Activate reject timer, if RRCComplete not received after 10 frames, reject UE */ + RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1; + /* Reject UE after 10 frames, LTE_RRCConnectionReestablishmentReject is triggered */ + RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres = 100; + } else { + LOG_E(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Generating NR_RRCReestablishment without UE_id(MAC) rnti %x\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + rnti); + } +#endif +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, ue_context->Srb0.Tx_buffer.payload_size); + memcpy (message_buffer, (uint8_t *) ue_context->Srb0.Tx_buffer.Payload, ue_context->Srb0.Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = ue_context->Srb0.Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#endif + +} + +//----------------------------------------------------------------------------- +void +rrc_gNB_process_RRCConnectionReestablishmentComplete( + const protocol_ctxt_t *const ctxt_pP, + const rnti_t reestablish_rnti, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t xid +) +//----------------------------------------------------------------------------- +{ + LOG_I(NR_RRC, + PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, processing NR_RRCConnectionReestablishmentComplete from UE (SRB1 Active)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + + NR_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList; + NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; + NR_DRB_ToAddModList_t **DRB_configList2 = NULL; + NR_SRB_ToAddMod_t *SRB2_config = NULL; + NR_DRB_ToAddMod_t *DRB_config = NULL; + //NR_SDAP_Config_t *sdap_config = NULL; + int i = 0; + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + + uint8_t next_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + int ret = 0; + ue_context_pP->ue_context.Status = NR_RRC_CONNECTED; + ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED + ue_context_pP->ue_context.reestablishment_xid = next_xid; + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; + + // get old configuration of SRB2 + if (*SRB_configList2 != NULL) { + if((*SRB_configList2)->list.count!=0) { + LOG_D(NR_RRC, "SRB_configList2(%p) count is %d\n SRB_configList2->list.array[0] addr is %p", + SRB_configList2, (*SRB_configList2)->list.count, (*SRB_configList2)->list.array[0]); + } + + for (i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { + if ((*SRB_configList2)->list.array[i]->srb_Identity == 2 ) { + LOG_D(NR_RRC, "get SRB2_config from (ue_context_pP->ue_context.SRB_configList2[%d])\n", xid); + SRB2_config = (*SRB_configList2)->list.array[i]; + break; + } + } + } + + // SRB2_config = CALLOC(1, sizeof(*SRB2_config)); + // SRB2_config->srb_Identity = 2; + + SRB_configList2 = &(ue_context_pP->ue_context.SRB_configList2[next_xid]); + DRB_configList2 = &(ue_context_pP->ue_context.DRB_configList2[next_xid]); + + if (*SRB_configList2) { + free(*SRB_configList2); + LOG_D(NR_RRC, "free(ue_context_pP->ue_context.SRB_configList2[%d])\n", next_xid); + } + + *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); + + if (SRB2_config != NULL) { + // Add SRB2 to SRB configuration list + ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config); + ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config); + LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList\n", + SRB2_config->srb_Identity); + LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList2[%d]\n", + SRB2_config->srb_Identity, next_xid); + } else { + // SRB configuration list only contains SRB1. + LOG_W(NR_RRC,"SRB2 configuration does not exist in SRB configuration list\n"); + } + + if (*DRB_configList2) { + free(*DRB_configList2); + LOG_D(NR_RRC, "free(ue_context_pP->ue_context.DRB_configList2[%d])\n", next_xid); + } + + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); + + if (DRB_configList != NULL) { + LOG_D(NR_RRC, "get DRB_config from (ue_context_pP->ue_context.DRB_configList)\n"); + + for (i = 0; (i < DRB_configList->list.count) && (i < 3); i++) { + DRB_config = DRB_configList->list.array[i]; + // Add DRB to DRB configuration list, for LTE_RRCConnectionReconfigurationComplete + ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config); + } + } + + ue_context_pP->ue_context.Srb1.Active = 1; + //ue_context_pP->ue_context.Srb2.Srb_info.Srb_id = 2; + + if (AMF_MODE_ENABLED) { + hashtable_rc_t h_rc; + int j; + rrc_ue_ngap_ids_t *rrc_ue_ngap_ids_p = NULL; + uint16_t ue_initial_id = ue_context_pP->ue_context.ue_initial_id; + uint32_t gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + gNB_RRC_INST *rrc_instance_p = RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(ctxt_pP->instance)]; + + if (gNB_ue_ngap_id > 0) { + h_rc = hashtable_get(rrc_instance_p->ngap_id2_ngap_ids, (hash_key_t)gNB_ue_ngap_id, (void **)&rrc_ue_ngap_ids_p); + + if (h_rc == HASH_TABLE_OK) { + rrc_ue_ngap_ids_p->ue_rnti = ctxt_pP->rnti; + } + } + + if (ue_initial_id != 0) { + h_rc = hashtable_get(rrc_instance_p->initial_id2_ngap_ids, (hash_key_t)ue_initial_id, (void **)&rrc_ue_ngap_ids_p); + + if (h_rc == HASH_TABLE_OK) { + rrc_ue_ngap_ids_p->ue_rnti = ctxt_pP->rnti; + } + } + + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req; + /* Save e RAB information for later */ + memset(&create_tunnel_req, 0, sizeof(create_tunnel_req)); + + for ( j = 0, i = 0; i < NB_RB_MAX; i++) { + if (ue_context_pP->ue_context.pdusession[i].status == PDU_SESSION_STATUS_ESTABLISHED || ue_context_pP->ue_context.pdusession[i].status == PDU_SESSION_STATUS_DONE) { + create_tunnel_req.pdusession_id[j] = ue_context_pP->ue_context.pdusession[i].param.pdusession_id; + create_tunnel_req.upf_NGu_teid[j] = ue_context_pP->ue_context.pdusession[i].param.gtp_teid; + memcpy(create_tunnel_req.upf_addr[j].buffer, + ue_context_pP->ue_context.pdusession[i].param.upf_addr.buffer, + sizeof(uint8_t)*20); + create_tunnel_req.upf_addr[j].length = ue_context_pP->ue_context.pdusession[i].param.upf_addr.length; + j++; + } + } + + create_tunnel_req.rnti = ctxt_pP->rnti; // warning put zero above + create_tunnel_req.num_tunnels = j; + ret = gtpv1u_update_ngu_tunnel( + ctxt_pP->instance, + &create_tunnel_req, + reestablish_rnti); + + if ( ret != 0 ) { + LOG_E(NR_RRC,"gtpv1u_update_ngu_tunnel failed,start to release UE %x\n",reestablish_rnti); + + // update s1u tunnel failed,reset rnti? + if (gNB_ue_ngap_id > 0) { + h_rc = hashtable_get(rrc_instance_p->ngap_id2_ngap_ids, (hash_key_t)gNB_ue_ngap_id, (void **)&rrc_ue_ngap_ids_p); + + if (h_rc == HASH_TABLE_OK ) { + rrc_ue_ngap_ids_p->ue_rnti = reestablish_rnti; + } + } + + if (ue_initial_id != 0) { + h_rc = hashtable_get(rrc_instance_p->initial_id2_ngap_ids, (hash_key_t)ue_initial_id, (void **)&rrc_ue_ngap_ids_p); + + if (h_rc == HASH_TABLE_OK ) { + rrc_ue_ngap_ids_p->ue_rnti = reestablish_rnti; + } + } + + ue_context_pP->ue_context.ue_release_timer_s1 = 1; + ue_context_pP->ue_context.ue_release_timer_thres_s1 = 100; + ue_context_pP->ue_context.ue_release_timer = 0; + ue_context_pP->ue_context.ue_reestablishment_timer = 0; + ue_context_pP->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ + ue_context_pP->ue_context.ul_failure_timer = 0; + return; + } + } /* AMF_MODE_ENABLED */ + + /* Update RNTI in ue_context */ + ue_context_pP->ue_id_rnti = ctxt_pP->rnti; // here ue_id_rnti is just a key, may be something else + ue_context_pP->ue_context.rnti = ctxt_pP->rnti; + + if (AMF_MODE_ENABLED) { + uint8_t send_security_mode_command = FALSE; + nr_rrc_pdcp_config_security( + ctxt_pP, + ue_context_pP, + send_security_mode_command); + LOG_D(NR_RRC, "set security successfully \n"); + } + + /* Add all NAS PDUs to the list */ + for (i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { + + /* TODO parameters yet to process ... */ + /* TODO should test if pdu session are Ok before! */ + ue_context_pP->ue_context.pdusession[i].status = PDU_SESSION_STATUS_DONE; + ue_context_pP->ue_context.pdusession[i].xid = xid; + LOG_D(NR_RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", + i, ue_context_pP->ue_context.pdusession[i].status, "PDU_SESSION_STATUS_DONE"); + } + + memset(buffer, 0, RRC_BUF_SIZE); + + size = do_RRCReconfiguration(ctxt_pP, buffer, + xid, + *SRB_configList2, + DRB_configList, + NULL, + NULL, + NULL, + NULL, // MeasObj_list, + NULL, + NULL); + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, + "[MSG] RRC Reconfiguration\n"); + + /* Free all NAS PDUs */ + for (i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { + if (ue_context_pP->ue_context.pdusession[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_context_pP->ue_context.pdusession[i].param.nas_pdu.buffer); + ue_context_pP->ue_context.pdusession[i].param.nas_pdu.buffer = NULL; + } + } + + if(size==65535) { + LOG_E(NR_RRC,"RRC decode err!!! do_RRCReconfiguration\n"); + return; + } else { + LOG_I(NR_RRC, + "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCConnectionReconfiguration (bytes %d, UE id %x)\n", + ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti); + LOG_D(NR_RRC, + "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_gNB_mui, ctxt_pP->module_id, DCCH); + MSC_LOG_TX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + buffer, + size, + MSC_AS_TIME_FMT" LTE_RRCConnectionReconfiguration UE %x MUI %d size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP->ue_context.rnti, + rrc_gNB_mui, + size); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); + memcpy (message_buffer, buffer, size); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_DCCH_DATA_IND); + GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + GNB_RRC_DCCH_DATA_IND (message_p).size = size; + itti_send_msg_to_task (TASK_RRC_UE_SIM, ctxt_pP->instance, message_p); +#else + nr_rrc_data_req( + ctxt_pP, + DCCH, + rrc_gNB_mui++, + SDU_CONFIRM_NO, + size, + buffer, + PDCP_TRANSMISSION_MODE_CONTROL); +#endif + } +} //----------------------------------------------------------------------------- /*------------------------------------------------------------------------------*/ @@ -823,30 +1448,33 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, int buffer_length, const int CC_id) { + module_id_t Idx; asn_dec_rval_t dec_rval; NR_UL_CCCH_Message_t *ul_ccch_msg = NULL; struct rrc_gNB_ue_context_s *ue_context_p = NULL; gNB_RRC_INST *gnb_rrc_inst = RC.nrrrc[ctxt_pP->module_id]; NR_RRCSetupRequest_IEs_t *rrcSetupRequest = NULL; - uint64_t random_value = 0; + NR_RRCReestablishmentRequest_IEs_t rrcReestablishmentRequest; + uint64_t random_value = 0; + int i; - dec_rval = uper_decode( NULL, - &asn_DEF_NR_UL_CCCH_Message, - (void **)&ul_ccch_msg, - (uint8_t *) buffer, - 100, - 0, - 0); + dec_rval = uper_decode( NULL, + &asn_DEF_NR_UL_CCCH_Message, + (void **)&ul_ccch_msg, + (uint8_t *) buffer, + 100, + 0, + 0); - if (dec_rval.consumed == 0) { - /* TODO */ - LOG_E(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" FATAL Error in receiving CCCH\n", - PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); - return -1; - } + if (dec_rval.consumed == 0) { + /* TODO */ + LOG_E(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" FATAL Error in receiving CCCH\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + return -1; + } - if (ul_ccch_msg->message.present == NR_UL_CCCH_MessageType_PR_c1) { - switch (ul_ccch_msg->message.choice.c1->present) { + if (ul_ccch_msg->message.present == NR_UL_CCCH_MessageType_PR_c1) { + switch (ul_ccch_msg->message.choice.c1->present) { case NR_UL_CCCH_MessageType__c1_PR_NOTHING: /* TODO */ LOG_I(NR_RRC, @@ -855,6 +1483,7 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, break; case NR_UL_CCCH_MessageType__c1_PR_rrcSetupRequest: + LOG_I(NR_RRC, "Received RRCSetupRequest on UL-CCCH-Message (UE rnti %x)\n", ctxt_pP->rnti); ue_context_p = rrc_gNB_get_ue_context(gnb_rrc_inst, ctxt_pP->rnti); if (ue_context_p != NULL) { rrc_gNB_free_mem_UE_context(ctxt_pP, ue_context_p); @@ -941,7 +1570,7 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, LOG_E(RRC, "%s:%d:%s: rrc_gNB_get_next_free_ue_context returned NULL\n", __FILE__, __LINE__, __FUNCTION__); } - if (ue_context_p != NULL) { + if (ue_context_p != NULL) { ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence = TRUE; ue_context_p->ue_context.ng_5G_S_TMSI_Part1 = s_tmsi_part1; } @@ -973,13 +1602,218 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, break; case NR_UL_CCCH_MessageType__c1_PR_rrcResumeRequest: - LOG_I(NR_RRC, "receive rrcResumeRequest message \n"); - /* TODO */ + LOG_I(NR_RRC, "receive rrcResumeRequest message \n"); break; case NR_UL_CCCH_MessageType__c1_PR_rrcReestablishmentRequest: LOG_I(NR_RRC, "receive rrcReestablishmentRequest message \n"); - /* TODO */ + LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)(buffer), buffer_length, + "[MSG] RRC Reestablishment Request\n"); + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT"MAC_gNB--- MAC_DATA_IND (rrcReestablishmentRequest on SRB0) --> RRC_gNB\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + + rrcReestablishmentRequest = ul_ccch_msg->message.choice.c1->choice.rrcReestablishmentRequest->rrcReestablishmentRequest; + LOG_I(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest cause %s\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ((rrcReestablishmentRequest.reestablishmentCause == NR_ReestablishmentCause_otherFailure) ? "Other Failure" : + (rrcReestablishmentRequest.reestablishmentCause == NR_ReestablishmentCause_handoverFailure) ? "Handover Failure" : + "reconfigurationFailure")); + { + uint16_t c_rnti = 0; + if (rrcReestablishmentRequest.ue_Identity.physCellId != RC.nrrrc[ctxt_pP->module_id]->carrier.physCellId) { + /* UE was moving from previous cell so quickly that RRCReestablishment for previous cell was recieved in this cell */ + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest ue_Identity.physCellId(%ld) is not equal to current physCellId(%d), fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + rrcReestablishmentRequest.ue_Identity.physCellId, + RC.nrrrc[ctxt_pP->module_id]->carrier.physCellId); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } + + LOG_D(NR_RRC, "physCellId is %ld\n", rrcReestablishmentRequest.ue_Identity.physCellId); + + for (i = 0; i < rrcReestablishmentRequest.ue_Identity.shortMAC_I.size; i++) { + LOG_D(NR_RRC, "rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[%d] = %x\n", + i, rrcReestablishmentRequest.ue_Identity.shortMAC_I.buf[i]); + } + + if (rrcReestablishmentRequest.ue_Identity.c_RNTI < 0 || + rrcReestablishmentRequest.ue_Identity.c_RNTI > 65535) { + /* c_RNTI range error should not happen */ + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest c_RNTI range error, fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } + + c_rnti = rrcReestablishmentRequest.ue_Identity.c_RNTI; + LOG_I(NR_RRC, "c_rnti is %x\n", c_rnti); + ue_context_p = rrc_gNB_get_ue_context(gnb_rrc_inst, c_rnti); + + if (ue_context_p == NULL) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest without UE context, fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } +#if(0) + int UE_id = find_nr_UE_id(ctxt_pP->module_id, c_rnti); + + if(UE_id == -1) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest without UE_id(MAC) rnti %x, fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),c_rnti); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } + + //previous rnti + rnti_t previous_rnti = 0; + + for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { + if (reestablish_rnti_map[i][1] == c_rnti) { + previous_rnti = reestablish_rnti_map[i][0]; + break; + } + } + + if(previous_rnti != 0) { + UE_id = find_nr_UE_id(ctxt_pP->module_id, previous_rnti); + + if(UE_id == -1) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RRCReestablishmentRequest without UE_id(MAC) previous rnti %x, fallback to RRC establishment\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),previous_rnti); + rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(ctxt_pP, CC_id); + break; + } + } +#endif + //c-plane not end + if((ue_context_p->ue_context.Status != NR_RRC_RECONFIGURED) && (ue_context_p->ue_context.reestablishment_cause == NR_ReestablishmentCause_spare1)) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCReestablishmentRequest (UE %x c-plane is not end), RRC establishment failed \n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),c_rnti); + /* TODO RRC Release ? */ + break; + } + + if(ue_context_p->ue_context.ue_reestablishment_timer > 0) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" RRRCReconfigurationComplete(Previous) don't receive, delete the Previous UE,\nprevious Status %d, new Status NR_RRC_RECONFIGURED\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context_p->ue_context.Status + ); + ue_context_p->ue_context.Status = NR_RRC_RECONFIGURED; + protocol_ctxt_t ctxt_old_p; + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt_old_p, + ctxt_pP->instance, + GNB_FLAG_YES, + c_rnti, + ctxt_pP->frame, + ctxt_pP->subframe); + rrc_gNB_process_RRCReconfigurationComplete(&ctxt_old_p, + ue_context_p, + ue_context_p->ue_context.reestablishment_xid); + + for (uint8_t pdusessionid = 0; pdusessionid < ue_context_p->ue_context.nb_of_pdusessions; pdusessionid++) { + if (ue_context_p->ue_context.pdusession[pdusessionid].status == PDU_SESSION_STATUS_DONE) { + ue_context_p->ue_context.pdusession[pdusessionid].status = PDU_SESSION_STATUS_ESTABLISHED; + } else { + ue_context_p->ue_context.pdusession[pdusessionid].status = PDU_SESSION_STATUS_FAILED; + } + } + } + + LOG_D(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" UE context: %p\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + ue_context_p); + /* reset timers */ + ue_context_p->ue_context.ul_failure_timer = 0; + ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 0; + // ue_context_p->ue_context.ue_release_timer_s1 = 0; + ue_context_p->ue_context.ue_release_timer_rrc = 0; + ue_context_p->ue_context.reestablishment_xid = -1; + + // insert C-RNTI to map + for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { + if (reestablish_rnti_map[i][0] == 0) { + reestablish_rnti_map[i][0] = ctxt_pP->rnti; + reestablish_rnti_map[i][1] = c_rnti; + LOG_D(NR_RRC, "reestablish_rnti_map[%d] [0] %x, [1] %x\n", + i, reestablish_rnti_map[i][0], reestablish_rnti_map[i][1]); + break; + } + } + + ue_context_p->ue_context.reestablishment_cause = rrcReestablishmentRequest.reestablishmentCause; + LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Accept reestablishment request from UE physCellId %ld cause %ld\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + rrcReestablishmentRequest.ue_Identity.physCellId, + ue_context_p->ue_context.reestablishment_cause); + + ue_context_p->ue_context.primaryCC_id = CC_id; + //LG COMMENT Idx = (ue_mod_idP * NB_RB_MAX) + DCCH; + Idx = DCCH; + // SRB1 + ue_context_p->ue_context.Srb1.Active = 1; + ue_context_p->ue_context.Srb1.Srb_info.Srb_id = Idx; + memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[0], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[1], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + // SRB2: set it to go through SRB1 with id 1 (DCCH) + ue_context_p->ue_context.Srb2.Active = 1; + ue_context_p->ue_context.Srb2.Srb_info.Srb_id = Idx; + memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[0], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[1], + &DCCH_LCHAN_DESC, + LCHAN_DESC_SIZE); + + rrc_gNB_generate_RRCReestablishment(ctxt_pP, ue_context_p, CC_id); + + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT"CALLING RLC CONFIG SRB1 (rbid %d)\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), + Idx); + MSC_LOG_TX_MESSAGE(MSC_RRC_GNB, + MSC_PDCP_GNB, + NULL, + 0, + MSC_AS_TIME_FMT" CONFIG_REQ UE %x SRB", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti); + // nr_rrc_pdcp_config_asn1_req(ctxt_pP, + // ue_context_p->ue_context.SRB_configList, + // NULL, + // NULL, + // 0xff, + // NULL, + // NULL, + // NULL, + // NULL, + // NULL, + // NULL); + + // if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { + // nr_rrc_rlc_config_asn1_req(ctxt_pP, + // ue_context_p->ue_context.SRB_configList, + // NULL, + // NULL, + // NULL, + // NULL); + // } + } break; case NR_UL_CCCH_MessageType__c1_PR_rrcSystemInfoRequest: @@ -1032,7 +1866,8 @@ rrc_gNB_decode_dcch( asn_dec_rval_t dec_rval; NR_UL_DCCH_Message_t *ul_dcch_msg = NULL; struct rrc_gNB_ue_context_s *ue_context_p = NULL; - // NR_RRCSetupComplete_t *rrcSetupComplete = NULL; + MessageDef *msg_delete_tunnels_p = NULL; + uint8_t xid; int i; @@ -1085,8 +1920,9 @@ rrc_gNB_decode_dcch( break; case NR_UL_DCCH_MessageType__c1_PR_rrcReconfigurationComplete: + LOG_I(NR_RRC, "Receive RRC Reconfiguration Complete message UE %x\n", ctxt_pP->rnti); if(!ue_context_p) { - LOG_I(NR_RRC, "Processing NR_RRCReconfigurationComplete UE %x, ue_context_p is NULL\n", ctxt_pP->rnti); + LOG_E(NR_RRC, "Processing NR_RRCReconfigurationComplete UE %x, ue_context_p is NULL\n", ctxt_pP->rnti); break; } @@ -1117,7 +1953,39 @@ rrc_gNB_decode_dcch( ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier); } - rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + if (AMF_MODE_ENABLED) { + if(ue_context_p->ue_context.pdu_session_release_command_flag == 1) { + xid = ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier; + ue_context_p->ue_context.pdu_session_release_command_flag = 0; + //gtp tunnel delete + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_GNB, GTPV1U_GNB_DELETE_TUNNEL_REQ); + memset(>PV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + + for(i = 0; i < NB_RB_MAX; i++) { + if(xid == ue_context_p->ue_context.pdusession[i].xid) { + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).pdusession_id[GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_pdusession++] = + ue_context_p->ue_context.gnb_gtp_psi[i]; + ue_context_p->ue_context.gnb_gtp_teid[i] = 0; + memset(&ue_context_p->ue_context.gnb_gtp_addrs[i], 0, sizeof(ue_context_p->ue_context.gnb_gtp_addrs[i])); + ue_context_p->ue_context.gnb_gtp_psi[i] = 0; + } + } + + itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->instance, msg_delete_tunnels_p); + //NGAP_PDUSESSION_RELEASE_RESPONSE + rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(ctxt_pP, ue_context_p, xid); + } else { + rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(ctxt_pP, + ue_context_p, + ul_dcch_msg->message.choice.c1->choice.rrcReconfigurationComplete->rrc_TransactionIdentifier); + } + } + + if (first_rrcreconfiguration == 0){ + first_rrcreconfiguration = 1; + rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p); + } break; @@ -1199,7 +2067,7 @@ rrc_gNB_decode_dcch( ctxt_pP, ue_context_p, ul_dcch_msg->message.choice.c1->choice.rrcSetupComplete->criticalExtensions.choice.rrcSetupComplete); - LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" UE State = RRC_CONNECTED \n", + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" UE State = NR_RRC_CONNECTED \n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); } @@ -1397,6 +2265,78 @@ rrc_gNB_decode_dcch( rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); break; + case NR_UL_DCCH_MessageType__c1_PR_rrcReestablishmentComplete: + LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, + "[MSG] NR_RRC Connection Reestablishment Complete\n"); + MSC_LOG_RX_MESSAGE( + MSC_RRC_GNB, + MSC_RRC_UE, + Rx_sdu, + sdu_sizeP, + MSC_AS_TIME_FMT" NR_RRCConnectionReestablishmentComplete UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, + sdu_sizeP); + LOG_I(NR_RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes " + "(rrcConnectionReestablishmentComplete) ---> RRC_gNB\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + DCCH, + sdu_sizeP); + { + rnti_t reestablish_rnti = 0; + + // select C-RNTI from map + for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { + if (reestablish_rnti_map[i][0] == ctxt_pP->rnti) { + reestablish_rnti = reestablish_rnti_map[i][1]; + ue_context_p = rrc_gNB_get_ue_context( + RC.nrrrc[ctxt_pP->module_id], + reestablish_rnti); + // clear currentC-RNTI from map + reestablish_rnti_map[i][0] = 0; + reestablish_rnti_map[i][1] = 0; + LOG_D(NR_RRC, "reestablish_rnti_map[%d] [0] %x, [1] %x\n", + i, reestablish_rnti_map[i][0], reestablish_rnti_map[i][1]); + break; + } + } + + if (!ue_context_p) { + LOG_E(NR_RRC, + PROTOCOL_NR_RRC_CTXT_UE_FMT" NR_RRCConnectionReestablishmentComplete without UE context, falt\n", + PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP)); + break; + } + +#if(0) + //clear + int UE_id = find_nr_UE_id(ctxt_pP->module_id, ctxt_pP->rnti); + + if(UE_id == -1) { + LOG_E(NR_RRC, + PROTOCOL_RRC_CTXT_UE_FMT" NR_RRCConnectionReestablishmentComplete without UE_id(MAC) rnti %x, fault\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ctxt_pP->rnti); + break; + } + + RC.nrmac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; +#endif + ue_context_p->ue_context.reestablishment_xid = -1; + + if (ul_dcch_msg->message.choice.c1->choice.rrcReestablishmentComplete->criticalExtensions.present == + NR_RRCReestablishmentComplete__criticalExtensions_PR_rrcReestablishmentComplete) { + rrc_gNB_process_RRCConnectionReestablishmentComplete(ctxt_pP, reestablish_rnti, ue_context_p, + ul_dcch_msg->message.choice.c1->choice.rrcReestablishmentComplete->rrc_TransactionIdentifier); + + } + + //ue_context_p->ue_context.ue_release_timer = 0; + ue_context_p->ue_context.ue_reestablishment_timer = 1; + // remove UE after 100 frames after LTE_RRCConnectionReestablishmentRelease is triggered + ue_context_p->ue_context.ue_reestablishment_timer_thres = 1000; + } + break; default: break; } @@ -1465,12 +2405,12 @@ void *rrc_gnb_task(void *args_p) { /* Messages from MAC */ case NR_RRC_MAC_CCCH_DATA_IND: - // PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, - // NR_RRC_MAC_CCCH_DATA_IND(msg_p).gnb_index, - // GNB_FLAG_YES, - // NR_RRC_MAC_CCCH_DATA_IND(msg_p).rnti, - // msg_p->ittiMsgHeader.lte_time.frame, - // msg_p->ittiMsgHeader.lte_time.slot); + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).gnb_index, + GNB_FLAG_YES, + NR_RRC_MAC_CCCH_DATA_IND(msg_p).rnti, + msg_p->ittiMsgHeader.lte_time.frame, + msg_p->ittiMsgHeader.lte_time.slot); LOG_I(NR_RRC,"Decoding CCCH : inst %d, CC_id %d, ctxt %p, sib_info_p->Rx_buffer.payload_size %d\n", instance, NR_RRC_MAC_CCCH_DATA_IND(msg_p).CC_id, @@ -1491,12 +2431,12 @@ void *rrc_gnb_task(void *args_p) { /* Messages from PDCP */ case NR_RRC_DCCH_DATA_IND: - // PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, - // instance, - // ENB_FLAG_YES, - // RRC_DCCH_DATA_IND(msg_p).rnti, - // msg_p->ittiMsgHeader.lte_time.frame, - // msg_p->ittiMsgHeader.lte_time.slot); + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, + instance, + GNB_FLAG_YES, + NR_RRC_DCCH_DATA_IND(msg_p).rnti, + msg_p->ittiMsgHeader.lte_time.frame, + msg_p->ittiMsgHeader.lte_time.slot); LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" Received on DCCH %d %s\n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(&ctxt), NR_RRC_DCCH_DATA_IND(msg_p).dcch_index, @@ -1515,6 +2455,13 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(msg_p, msg_name_p, instance); break; + case NGAP_PDUSESSION_RELEASE_COMMAND: + rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(msg_p, msg_name_p, instance); + break; + + case GTPV1U_GNB_DELETE_TUNNEL_RESP: + break; + /* #if defined(ENABLE_USE_MME) @@ -1588,6 +2535,7 @@ void *rrc_gnb_task(void *args_p) { case NGAP_INITIAL_CONTEXT_SETUP_REQ: rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p, msg_name_p, instance); + break; case X2AP_ENDC_SGNB_RELEASE_REQUEST: LOG_I(NR_RRC, "Received ENDC sgNB release request from X2AP \n"); @@ -1687,11 +2635,11 @@ rrc_gNB_generate_SecurityModeCommand( rrc_gNB_mui, size); #ifdef ITTI_SIM - MessageDef *message_p; + MessageDef *message_p; uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB_SIM, TASK_RRC_UE_SIM,size); + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM,size); memcpy (message_buffer, buffer, size); - message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, GNB_RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_DCCH_DATA_IND); GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_DCCH_DATA_IND (message_p).size = size; @@ -1788,9 +2736,9 @@ rrc_gNB_generate_UECapabilityEnquiry( size); #ifdef ITTI_SIM uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_GNB_SIM, TASK_RRC_UE_SIM, size); + message_buffer = itti_malloc (TASK_RRC_GNB, TASK_RRC_UE_SIM, size); memcpy (message_buffer, buffer, size); - message_p = itti_alloc_new_message (TASK_RRC_GNB_SIM, GNB_RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_GNB, GNB_RRC_DCCH_DATA_IND); GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_DCCH_DATA_IND (message_p).size = size; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index a7c1aa95d1..01a414dd76 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -1289,3 +1289,165 @@ rrc_gNB_send_NGAP_UE_CAPABILITIES_IND( LOG_I(NR_RRC,"Send message to ngap: NGAP_UE_CAPABILITIES_IND\n"); } +//------------------------------------------------------------------------------ +void +rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid +) +//------------------------------------------------------------------------------ +{ + int pdu_sessions_released = 0; + MessageDef *msg_p; + msg_p = itti_alloc_new_message (TASK_RRC_GNB, NGAP_PDUSESSION_RELEASE_RESPONSE); + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).gNB_ue_ngap_id = ue_context_pP->ue_context.gNB_ue_ngap_id; + + for (int i = 0; i < NB_RB_MAX; i++) { + if (xid == ue_context_pP->ue_context.pdusession[i].xid) { + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).pdusession_release[pdu_sessions_released].pdusession_id = + ue_context_pP->ue_context.pdusession[i].param.pdusession_id; + pdu_sessions_released++; + //clear + memset(&ue_context_pP->ue_context.pdusession[i], 0, sizeof(pdu_session_param_t)); + } + } + + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).nb_of_pdusessions_released = pdu_sessions_released; + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).nb_of_pdusessions_failed = ue_context_pP->ue_context.nb_release_of_pdusessions; + memcpy(&(NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).pdusessions_failed[0]), &ue_context_pP->ue_context.pdusessions_release_failed[0], + sizeof(pdusession_failed_t)*ue_context_pP->ue_context.nb_release_of_pdusessions); + ue_context_pP->ue_context.setup_pdu_sessions -= pdu_sessions_released; + LOG_I(NR_RRC,"NGAP PDUSESSION RELEASE RESPONSE: GNB_UE_NGAP_ID %d release_pdu_sessions %d setup_pdu_sessions %d \n", + NGAP_PDUSESSION_RELEASE_RESPONSE (msg_p).gNB_ue_ngap_id, + pdu_sessions_released, ue_context_pP->ue_context.setup_pdu_sessions); + itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p); + + //clear xid + for(int i = 0; i < NB_RB_MAX; i++) { + ue_context_pP->ue_context.pdusession[i].xid = -1; + } + + //clear release pdusessions + ue_context_pP->ue_context.nb_release_of_pdusessions = 0; + memset(&ue_context_pP->ue_context.pdusessions_release_failed[0], 0, sizeof(pdusession_failed_t)*NGAP_MAX_PDUSESSION); +} + +//------------------------------------------------------------------------------ +int +rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +) +//------------------------------------------------------------------------------ +{ + uint32_t gNB_ue_ngap_id; + rrc_gNB_ue_context_t *ue_context_p = NULL; + protocol_ctxt_t ctxt; + pdusession_release_t pdusession_release_params[NGAP_MAX_PDUSESSION]; + uint8_t nb_pdusessions_torelease; + MessageDef *msg_delete_tunnels_p = NULL; + uint8_t xid; + int i, pdusession; + uint8_t b_existed,is_existed; + uint8_t pdusession_release_drb = 0; + + memcpy(&pdusession_release_params[0], &(NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).pdusession_release_params[0]), + sizeof(pdusession_release_t)*NGAP_MAX_PDUSESSION); + gNB_ue_ngap_id = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id; + nb_pdusessions_torelease = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).nb_pdusessions_torelease; + if (nb_pdusessions_torelease > NGAP_MAX_PDUSESSION) { + return -1; + } + ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, UE_INITIAL_ID_INVALID, gNB_ue_ngap_id); + LOG_I(NR_RRC, "[gNB %d] Received %s: gNB_ue_ngap_id %d \n", instance, msg_name, gNB_ue_ngap_id); + + if (ue_context_p != NULL) { + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + xid = rrc_gNB_get_next_transaction_identifier(ctxt.module_id); + LOG_I(NR_RRC,"PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %d release_pdusessions %d \n", + NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).amf_ue_ngap_id&0x000000FFFFFFFFFF, gNB_ue_ngap_id, nb_pdusessions_torelease); + + for (pdusession = 0; pdusession < nb_pdusessions_torelease; pdusession++) { + b_existed = 0; + is_existed = 0; + + for (i = pdusession-1; i >= 0; i--) { + if (pdusession_release_params[pdusession].pdusession_id == pdusession_release_params[i].pdusession_id) { + is_existed = 1; + break; + } + } + + if(is_existed == 1) { + // pdusession_id is existed + continue; + } + + for (i = 0; i < NR_NB_RB_MAX; i++) { + if (pdusession_release_params[pdusession].pdusession_id == ue_context_p->ue_context.pdusession[i].param.pdusession_id) { + b_existed = 1; + break; + } + } + + if(b_existed == 0) { + // no pdusession_id + LOG_I(NR_RRC, "no pdusession_id \n"); + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].pdusession_id = pdusession_release_params[pdusession].pdusession_id; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause = NGAP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause_value = 30; + ue_context_p->ue_context.nb_release_of_pdusessions++; + } else { + if(ue_context_p->ue_context.pdusession[i].status == PDU_SESSION_STATUS_FAILED) { + ue_context_p->ue_context.pdusession[i].xid = xid; + continue; + } else if(ue_context_p->ue_context.pdusession[i].status == PDU_SESSION_STATUS_ESTABLISHED) { + LOG_I(NR_RRC, "RELEASE pdusession %d \n", ue_context_p->ue_context.pdusession[i].param.pdusession_id); + ue_context_p->ue_context.pdusession[i].status = PDU_SESSION_STATUS_TORELEASE; + ue_context_p->ue_context.pdusession[i].xid = xid; + pdusession_release_drb++; + } else { + // pdusession_id status NG + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].pdusession_id = pdusession_release_params[pdusession].pdusession_id; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause = NGAP_CAUSE_RADIO_NETWORK; + ue_context_p->ue_context.pdusessions_release_failed[ue_context_p->ue_context.nb_release_of_pdusessions].cause_value = 0; + ue_context_p->ue_context.nb_release_of_pdusessions++; + } + } + } + + if(pdusession_release_drb > 0) { + //TODO RRCReconfiguration To UE + LOG_I(NR_RRC, "Send RRCReconfiguration To UE \n"); + rrc_gNB_generate_dedicatedRRCReconfiguration_release(&ctxt, ue_context_p, xid, NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).nas_pdu.length, NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).nas_pdu.buffer); + } else { + //gtp tunnel delete + LOG_I(NR_RRC, "gtp tunnel delete \n"); + msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_GNB, GTPV1U_GNB_DELETE_TUNNEL_REQ); + memset(>PV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; + + for(i = 0; i < NB_RB_MAX; i++) { + if(xid == ue_context_p->ue_context.pdusession[i].xid) { + GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).pdusession_id[GTPV1U_GNB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_pdusession++] = ue_context_p->ue_context.gnb_gtp_psi[i]; + ue_context_p->ue_context.gnb_gtp_teid[i] = 0; + memset(&ue_context_p->ue_context.gnb_gtp_addrs[i], 0, sizeof(ue_context_p->ue_context.gnb_gtp_addrs[i])); + ue_context_p->ue_context.gnb_gtp_psi[i] = 0; + } + } + + itti_send_msg_to_task(TASK_GTPV1_U, instance, msg_delete_tunnels_p); + //NGAP_PDUSESSION_RELEASE_RESPONSE + rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(&ctxt, ue_context_p, xid); + LOG_I(NR_RRC, "Send PDU Session Release Response \n"); + } + } else { + LOG_E(NR_RRC, "PDU Session Release Command: AMF_UE_NGAP_ID %lu GNB_UE_NGAP_ID %d Error ue_context_p NULL \n", + NGAP_PDUSESSION_RELEASE_COMMAND (msg_p).amf_ue_ngap_id&0x000000FFFFFFFFFF, NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id); + return -1; + } + + return 0; +} diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 85f4f183e6..f13c468f94 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -142,4 +142,25 @@ rrc_gNB_send_NGAP_UE_CAPABILITIES_IND( NR_UL_DCCH_Message_t *const ul_dcch_msg ); +int +rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND( + MessageDef *msg_p, + const char *msg_name, + instance_t instance +); + +void +rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + uint8_t xid +); + +void +nr_rrc_pdcp_config_security( + const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + const uint8_t send_security_mode_command +); + #endif diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index 757c35d7bc..988db09cc1 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -134,6 +134,7 @@ rrc_gNB_allocate_new_UE_context( new_p->local_uid = nr_uid_linear_allocator_new(rrc_instance_pP); for(int i = 0; i < NB_RB_MAX; i++) { + new_p->ue_context.e_rab[i].xid = -1; new_p->ue_context.pdusession[i].xid = -1; new_p->ue_context.modify_e_rab[i].xid = -1; } diff --git a/openair2/RRC/NR/rrc_gNB_internode.c b/openair2/RRC/NR/rrc_gNB_internode.c index cacff5cf5c..3c8d75edfa 100644 --- a/openair2/RRC/NR/rrc_gNB_internode.c +++ b/openair2/RRC/NR/rrc_gNB_internode.c @@ -37,6 +37,7 @@ #include "NR_UE-CapabilityRAT-ContainerList.h" #include "LTE_UE-CapabilityRAT-ContainerList.h" #include "NR_CG-Config.h" +#include "executables/softmodem-common.h" int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m) { if (CG_ConfigInfo->criticalExtensions.present == NR_CG_ConfigInfo__criticalExtensions_PR_c1) { @@ -95,33 +96,48 @@ int generate_CG_Config(gNB_RRC_INST *rrc, (const char *)buffer, (enc_rval.encoded+7)>>3); total_size = (enc_rval.encoded+7)>>3; - LOG_I(RRC,"Dumping NR_RRCReconfiguration message (%jd bytes)\n",(enc_rval.encoded+7)>>3); - for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { - printf("%02x",((uint8_t *)buffer)[i]); + FILE *fd; // file to be generated for nr-ue + if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0) { + // This is for phytest only, emulate first X2 message if uecap.raw file is present + LOG_I(RRC,"Dumping NR_RRCReconfiguration message (%jd bytes)\n",(enc_rval.encoded+7)>>3); + for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { + printf("%02x",((uint8_t *)buffer)[i]); + } + printf("\n"); + fd = fopen("reconfig.raw","w"); + if (fd != NULL) { + fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); + } + fclose(fd); } - - printf("\n"); - FILE *fd = fopen("reconfig.raw","w"); - fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); - fclose(fd); + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RadioBearerConfig, NULL, (void *)rbconfig, buffer, 1024); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); + enc_rval.failed_type->name, enc_rval.encoded); cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config = calloc(1,sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config, - (const char *)buffer, - (enc_rval.encoded+7)>>3); - LOG_I(RRC,"Dumping scg_RB_Config message (%jd bytes)\n",(enc_rval.encoded+7)>>3); + (const char *)buffer, + (enc_rval.encoded+7)>>3); - for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { - printf("%02x",((uint8_t *)buffer)[i]); + + + if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0) { + + LOG_I(RRC,"Dumping scg_RB_Config message (%jd bytes)\n",(enc_rval.encoded+7)>>3); + for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { + printf("%02x",((uint8_t *)buffer)[i]); + } + + printf("\n"); + fd = fopen("rbconfig.raw","w"); + if (fd != NULL) { + fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); + } + fclose(fd); } - - printf("\n"); - fd = fopen("rbconfig.raw","w"); - fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); - fclose(fd); + total_size = total_size + ((enc_rval.encoded+7)>>3); return(total_size); } diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index fbb4eaf3d5..28646384cf 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -183,15 +183,15 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ if (m->nb_e_rabs_tobeadded>0) { for (int i=0; inb_e_rabs_tobeadded; i++) { - // Add the new E-RABs at the corresponding rrc ue context of the gNB - ue_context_p->ue_context.pdusession[i].param.pdusession_id = m->e_rabs_tobeadded[i].e_rab_id; - ue_context_p->ue_context.pdusession[i].param.gtp_teid = m->e_rabs_tobeadded[i].gtp_teid; - memcpy(&ue_context_p->ue_context.pdusession[i].param.upf_addr, &m->e_rabs_tobeadded[i].sgw_addr, sizeof(transport_layer_addr_t)); - ue_context_p->ue_context.nb_of_pdusessions++; + // Add the new E-RABs at the corresponding rrc ue context of the gNB + ue_context_p->ue_context.e_rab[i].param.e_rab_id = m->e_rabs_tobeadded[i].e_rab_id; + ue_context_p->ue_context.e_rab[i].param.gtp_teid = m->e_rabs_tobeadded[i].gtp_teid; + memcpy(&ue_context_p->ue_context.e_rab[i].param.sgw_addr, &m->e_rabs_tobeadded[i].sgw_addr, sizeof(transport_layer_addr_t)); + ue_context_p->ue_context.nb_of_e_rabs++; //Fill the required E-RAB specific information for the creation of the S1-U tunnel between the gNB and the SGW - create_tunnel_req.eps_bearer_id[i] = ue_context_p->ue_context.pdusession[i].param.pdusession_id; - create_tunnel_req.sgw_S1u_teid[i] = ue_context_p->ue_context.pdusession[i].param.gtp_teid; - memcpy(&create_tunnel_req.sgw_addr[i], &ue_context_p->ue_context.pdusession[i].param.upf_addr, sizeof(transport_layer_addr_t)); + create_tunnel_req.eps_bearer_id[i] = ue_context_p->ue_context.e_rab[i].param.e_rab_id; + create_tunnel_req.sgw_S1u_teid[i] = ue_context_p->ue_context.e_rab[i].param.gtp_teid; + memcpy(&create_tunnel_req.sgw_addr[i], &ue_context_p->ue_context.e_rab[i].param.sgw_addr, sizeof(transport_layer_addr_t)); inde_list[i] = i; LOG_I(RRC,"S1-U tunnel: index %d target sgw ip %d.%d.%d.%d length %d gtp teid %u\n", i, @@ -218,8 +218,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).nb_e_rabs_admitted_tobeadded = m->nb_e_rabs_tobeadded; X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).target_assoc_id = m->target_assoc_id; - for(int i=0; iue_context.nb_of_pdusessions; i++) { - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].e_rab_id = ue_context_p->ue_context.pdusession[i].param.pdusession_id; + for(int i=0; iue_context.nb_of_e_rabs; i++) { + X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].e_rab_id = ue_context_p->ue_context.e_rab[i].param.e_rab_id; X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gtp_teid = create_tunnel_resp.enb_S1u_teid[i]; memcpy(&X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr, &create_tunnel_resp.enb_addr, sizeof(transport_layer_addr_t)); //The length field in the X2AP targetting structure is expected in bits but the create_tunnel_resp returns the address length in bytes @@ -243,12 +243,9 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ } } else LOG_W(RRC, "No E-RAB to be added received from SgNB Addition Request message \n"); - } - if (m != NULL) { X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).MeNB_ue_x2_id = m->ue_x2_id; X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).SgNB_ue_x2_id = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity; - //X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = CG_Config_size; //Need to verify correct value for the buffer_size // Send to X2 entity to transport to MeNB asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_Config, @@ -258,6 +255,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ 1024); X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3; itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding + } else if (get_softmodem_params()->do_ra) { + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, ue_context_p->ue_id_rnti, 0, 0,rrc->module_id); } rrc->Nb_ue++; @@ -272,6 +271,15 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ ue_context_p->ue_id_rnti, ue_context_p->ue_context.secondaryCellGroup); + if(m == NULL){ + LOG_W(RRC, "Calling RRC PDCP/RLC ASN1 request functions for protocol context %p with module_id %d, rnti %x, frame %d, subframe %d eNB_index %d \n", &ctxt, + ctxt.module_id, + ctxt.rnti, + ctxt.frame, + ctxt.subframe, + ctxt.eNB_index); + } + nr_rrc_pdcp_config_asn1_req( &ctxt, (NR_SRB_ToAddModList_t *) NULL, @@ -292,6 +300,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_ (LTE_PMCH_InfoList_r9_t *) NULL, ue_context_p->ue_context.secondaryCellGroup->rlc_BearerToAddModList); + LOG_D(RRC, "%s:%d: done RRC PDCP/RLC ASN1 request for UE rnti %x\n", __FUNCTION__, __LINE__, ctxt.rnti); + } void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) { diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 197c3f1f87..29bf2fde06 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -43,6 +43,7 @@ #include "common/utils/nr/nr_common.h" #include "SIMULATION/TOOLS/sim.h" #include "executables/softmodem-common.h" +#include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #define false 0 #define true 1 @@ -57,66 +58,33 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n"); AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n"); - if(servingcellconfigcommon->ssb_PositionsInBurst->present !=2) - AssertFatal(1==0,"Currenrly implemented only for medium size SSB bitmap\n"); - uint8_t bitmap = servingcellconfigcommon->ssb_PositionsInBurst->choice.mediumBitmap.buf[0]; + uint64_t bitmap=0; + switch (servingcellconfigcommon->ssb_PositionsInBurst->present) { + case 1 : + bitmap = ((uint64_t) servingcellconfigcommon->ssb_PositionsInBurst->choice.shortBitmap.buf[0])<<56; + break; + case 2 : + bitmap = ((uint64_t) servingcellconfigcommon->ssb_PositionsInBurst->choice.mediumBitmap.buf[0])<<56; + break; + case 3 : + for (int i=0; i<8; i++) { + bitmap |= (((uint64_t) servingcellconfigcommon->ssb_PositionsInBurst->choice.longBitmap.buf[i])<<((7-i)*8)); + } + break; + default: + AssertFatal(1==0,"SSB bitmap size value %d undefined (allowed values 1,2,3) \n", servingcellconfigcommon->ssb_PositionsInBurst->present); + } memset(secondaryCellGroup,0,sizeof(NR_CellGroupConfig_t)); secondaryCellGroup->cellGroupId = scg_id; NR_RLC_BearerConfig_t *RLC_BearerConfig = calloc(1,sizeof(*RLC_BearerConfig)); - RLC_BearerConfig->logicalChannelIdentity = 4; - RLC_BearerConfig->servedRadioBearer = calloc(1,sizeof(*RLC_BearerConfig->servedRadioBearer)); - RLC_BearerConfig->servedRadioBearer->present = NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity; - RLC_BearerConfig->servedRadioBearer->choice.drb_Identity=1; - RLC_BearerConfig->reestablishRLC=calloc(1,sizeof(*RLC_BearerConfig->reestablishRLC)); - *RLC_BearerConfig->reestablishRLC=NR_RLC_BearerConfig__reestablishRLC_true; - RLC_BearerConfig->rlc_Config=calloc(1,sizeof(*RLC_BearerConfig->rlc_Config)); + nr_rlc_bearer_init(RLC_BearerConfig); + if (get_softmodem_params()->do_ra) + nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_um_Bi_Directional); + else + nr_drb_config(RLC_BearerConfig->rlc_Config, NR_RLC_Config_PR_am); + nr_rlc_bearer_init_ul_spec(RLC_BearerConfig->mac_LogicalChannelConfig); -#if 0 - - // RLC UM Bi-directional Bearer configuration - RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_um_Bi_Directional; - RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional)); - RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->ul_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; - - RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.sn_FieldLength = NR_SN_FieldLengthUM_size12; - RLC_BearerConfig->rlc_Config->choice.um_Bi_Directional->dl_UM_RLC.t_Reassembly = NR_T_Reassembly_ms15; - -#else - - // RLC AM Bearer configuration - RLC_BearerConfig->rlc_Config->present = NR_RLC_Config_PR_am; - RLC_BearerConfig->rlc_Config->choice.am = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am)); - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = NR_T_PollRetransmit_ms45; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollPDU = NR_PollPDU_p64; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.pollByte = NR_PollByte_kB500; - RLC_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = NR_UL_AM_RLC__maxRetxThreshold_t32; - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1,sizeof(*RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength)); - *RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size18; - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = NR_T_Reassembly_ms15; - RLC_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = NR_T_StatusProhibit_ms15; - -#endif - - RLC_BearerConfig->mac_LogicalChannelConfig = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig)); - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters)); - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority = 1; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bucketSizeDuration = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedServingCells = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->allowedSCS_List = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->maxPUSCH_Duration = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->configuredGrantType1Allowed = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = calloc(1,sizeof(*RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup)); - *RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = 1; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = NULL; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = false; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = false; - RLC_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL; secondaryCellGroup->rlc_BearerToAddModList = calloc(1,sizeof(*secondaryCellGroup->rlc_BearerToAddModList)); ASN_SEQUENCE_ADD(&secondaryCellGroup->rlc_BearerToAddModList->list, RLC_BearerConfig); secondaryCellGroup->mac_CellGroupConfig=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig)); @@ -251,9 +219,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->tci_StatesToAddModList)); int n_ssb = 0; - NR_TCI_State_t *tcic[8]; - for (int i=0;i<8;i++) { - if ((bitmap>>(7-i))&0x01){ + NR_TCI_State_t *tcic[64]; + for (int i=0;i<64;i++) { + if ((bitmap>>(63-i))&0x01){ tcic[i]=calloc(1,sizeof(*tcic[i])); tcic[i]->tci_StateId=n_ssb; tcic[i]->qcl_Type1.cell=NULL; @@ -362,7 +330,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rateMatchPatternGroup1=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rateMatchPatternGroup2=NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rbg_Size=NR_PDSCH_Config__rbg_Size_config1; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table=NULL; + if (!get_softmodem_params()->use_256qam_table) { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table=NULL; + } else { + secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table)); + *secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256; + } secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n1; secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling; @@ -412,12 +385,21 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->controlResourceSetZero=NULL; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet=calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet)); + int curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275); + NR_ControlResourceSet_t *coreset = calloc(1,sizeof(*coreset)); coreset->controlResourceSetId=1; - // frequencyDomainResources '11111111 11111111 00000000 00000000 00000000 00000'B, + // frequency domain resources depends on BWP size + // options are 24, 48 or 96 coreset->frequencyDomainResources.buf = calloc(1,6); - coreset->frequencyDomainResources.buf[0] = 0xff; - coreset->frequencyDomainResources.buf[1] = 0xff; + if (curr_bwp < 48) + coreset->frequencyDomainResources.buf[0] = 0xf0; + else + coreset->frequencyDomainResources.buf[0] = 0xff; + if (curr_bwp < 96) + coreset->frequencyDomainResources.buf[1] = 0; + else + coreset->frequencyDomainResources.buf[1] = 0xff; coreset->frequencyDomainResources.buf[2] = 0; coreset->frequencyDomainResources.buf[3] = 0; coreset->frequencyDomainResources.buf[4] = 0; @@ -429,9 +411,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco coreset->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; coreset->tci_StatesPDCCH_ToAddList=calloc(1,sizeof(*coreset->tci_StatesPDCCH_ToAddList)); - NR_TCI_StateId_t *tci[8]; - for (int i=0;i<8;i++) { - if ((bitmap>>(7-i))&0x01){ + NR_TCI_StateId_t *tci[64]; + for (int i=0;i<64;i++) { + if ((bitmap>>(63-i))&0x01){ tci[i]=calloc(1,sizeof(*tci[i])); *tci[i] = i; ASN_SEQUENCE_ADD(&coreset->tci_StatesPDCCH_ToAddList->list,tci[i]); @@ -531,7 +513,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ss2->nrofCandidates=calloc(1,sizeof(*ss2->nrofCandidates)); ss2->nrofCandidates->aggregationLevel1 = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; ss2->nrofCandidates->aggregationLevel2 = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; - ss2->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; + if (curr_bwp < 48) + ss2->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + else if (curr_bwp < 96) + ss2->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n2; + else + ss2->nrofCandidates->aggregationLevel4 = NR_SearchSpace__nrofCandidates__aggregationLevel4_n4; ss2->nrofCandidates->aggregationLevel8 = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; ss2->nrofCandidates->aggregationLevel16 = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; ss2->searchSpaceType=calloc(1,sizeof(*ss2->searchSpaceType)); @@ -653,9 +640,9 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco n_ssb = 0; - NR_TCI_State_t *tcid[8]; - for (int i=0;i<8;i++) { - if ((bitmap>>(7-i))&0x01){ + NR_TCI_State_t *tcid[64]; + for (int i=0;i<64;i++) { + if ((bitmap>>(63-i))&0x01){ tcid[i]=calloc(1,sizeof(*tcid[i])); tcid[i]->tci_StateId=n_ssb; tcid[i]->qcl_Type1.cell=NULL; @@ -680,7 +667,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup1=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup2=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->rbg_Size=NR_PDSCH_Config__rbg_Size_config1; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL; + if (!get_softmodem_params()->use_256qam_table) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL; + } else { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table)); + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256; + } bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI)); *bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n1; bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling; @@ -706,7 +698,12 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup1=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->rateMatchPatternGroup2=NULL; bwp->bwp_Dedicated->pdsch_Config->choice.setup->rbg_Size=NR_PDSCH_Config__rbg_Size_config1; - bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL; + if (!get_softmodem_params()->use_256qam_table) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table=NULL; + } else { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table)); + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table = NR_PDSCH_Config__mcs_Table_qam256; + } bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI)); *bwp->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI = NR_PDSCH_Config__maxNrofCodeWordsScheduledByDCI_n1; bwp->bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling; @@ -915,7 +912,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco NR_PUCCH_Resource_t *pucchres2=calloc(1,sizeof(*pucchres2)); NR_PUCCH_Resource_t *pucchres3=calloc(1,sizeof(*pucchres3)); pucchres0->pucch_ResourceId=1; - pucchres0->startingPRB=48; + pucchres0->startingPRB=8; pucchres0->intraSlotFrequencyHopping=NULL; pucchres0->secondHopPRB=NULL; pucchres0->format.present= NR_PUCCH_Resource__format_PR_format0; @@ -926,7 +923,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres0); pucchres1->pucch_ResourceId=2; - pucchres1->startingPRB=48; + pucchres1->startingPRB=8; pucchres1->intraSlotFrequencyHopping=NULL; pucchres1->secondHopPRB=NULL; pucchres1->format.present= NR_PUCCH_Resource__format_PR_format0; @@ -937,23 +934,23 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres1); pucchres2->pucch_ResourceId=3; - pucchres2->startingPRB=40; + pucchres2->startingPRB=0; pucchres2->intraSlotFrequencyHopping=NULL; pucchres2->secondHopPRB=NULL; pucchres2->format.present= NR_PUCCH_Resource__format_PR_format2; pucchres2->format.choice.format2=calloc(1,sizeof(*pucchres2->format.choice.format2)); - pucchres2->format.choice.format2->nrofPRBs=4; + pucchres2->format.choice.format2->nrofPRBs=8; pucchres2->format.choice.format2->nrofSymbols=1; pucchres2->format.choice.format2->startingSymbolIndex=13; ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres2); pucchres3->pucch_ResourceId=4; - pucchres3->startingPRB=40; + pucchres3->startingPRB=0; pucchres3->intraSlotFrequencyHopping=NULL; pucchres3->secondHopPRB=NULL; pucchres3->format.present= NR_PUCCH_Resource__format_PR_format2; pucchres3->format.choice.format2=calloc(1,sizeof(*pucchres3->format.choice.format2)); - pucchres3->format.choice.format2->nrofPRBs=4; + pucchres3->format.choice.format2->nrofPRBs=8; pucchres3->format.choice.format2->nrofSymbols=1; pucchres3->format.choice.format2->startingSymbolIndex=12; ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres3); @@ -1076,45 +1073,14 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco NR_CSI_SSB_ResourceSet_t *ssbresset0 = calloc(1,sizeof(*ssbresset0)); ssbresset0->csi_SSB_ResourceSetId=0; - if ((bitmap>>7)&0x01){ - NR_SSB_Index_t *ssbresset00=calloc(1,sizeof(*ssbresset00)); - *ssbresset00=0; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset00); - } - if ((bitmap>>6)&0x01) { - NR_SSB_Index_t *ssbresset01=calloc(1,sizeof(*ssbresset01)); - *ssbresset01=1; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset01); - } - if ((bitmap>>5)&0x01) { - NR_SSB_Index_t *ssbresset02=calloc(1,sizeof(*ssbresset02)); - *ssbresset02=2; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset02); - } - if ((bitmap>>4)&0x01) { - NR_SSB_Index_t *ssbresset03=calloc(1,sizeof(*ssbresset03)); - *ssbresset03=3; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset03); - } - if ((bitmap>>3)&0x01) { - NR_SSB_Index_t *ssbresset04=calloc(1,sizeof(*ssbresset04)); - *ssbresset04=4; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset04); - } - if ((bitmap>>2)&0x01) { - NR_SSB_Index_t *ssbresset05=calloc(1,sizeof(*ssbresset05)); - *ssbresset05=5; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset05); - } - if ((bitmap>>1)&0x01) { - NR_SSB_Index_t *ssbresset06=calloc(1,sizeof(*ssbresset06)); - *ssbresset06=6; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset06); - } - if ((bitmap)&0x01) { - NR_SSB_Index_t *ssbresset07=calloc(1,sizeof(*ssbresset07)); - *ssbresset07=7; - ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset07); + + NR_SSB_Index_t *ssbresset[64]; + for (int i=0;i<64;i++) { + if ((bitmap>>(63-i))&0x01){ + ssbresset[i]=calloc(1,sizeof(*ssbresset[i])); + *ssbresset[i] = i; + ASN_SEQUENCE_ADD(&ssbresset0->csi_SSB_ResourceList.list,ssbresset[i]); + } } ASN_SEQUENCE_ADD(&csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list,ssbresset0); @@ -1276,5 +1242,37 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) { xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); } +/* Function to set or overwrite PTRS DL RRC parameters */ +void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset) +{ + int i=0; + /* check for memory allocation */ + if(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS == NULL) { + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup; + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup= calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = calloc(1,sizeof(long)); + bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = calloc(1,sizeof(long)); + /* Fill the given values */ + for(i = 0; i < 2; i++) { + ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list,&ptrsNrb[i]); + } + for(i = 0; i < 3; i++) { + ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list,&ptrsMcs[i]); + } + }// if memory exist then over write the old values + else { + for(i = 0; i < 2; i++) { + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] = ptrsNrb[i]; + } + for(i = 0; i < 3; i++) { + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] = ptrsMcs[i]; + } + } + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = *epre_Ratio; + *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = *reOffset; +} #endif diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index c031d1c5af..321144fee5 100755 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -117,7 +117,17 @@ uint8_t do_NR_RRCReconfigurationComplete( const uint8_t Transaction_id ); +void rrc_ue_generate_RRCReestablishmentRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ); + +void +nr_rrc_ue_generate_rrcReestablishmentComplete( + const protocol_ctxt_t *const ctxt_pP, + NR_RRCReestablishment_t *rrcReestablishment, + uint8_t gNB_index +); + mui_t nr_rrc_mui=0; +uint8_t first_rrcreconfigurationcomplete = 0; static Rrc_State_NR_t nr_rrc_get_state (module_id_t ue_mod_idP) { return NR_UE_rrc_inst[ue_mod_idP].nrRrcState; @@ -1383,9 +1393,9 @@ static void rrc_ue_generate_RRCSetupComplete( #ifdef ITTI_SIM MessageDef *message_p; uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_UE_SIM, TASK_RRC_GNB_SIM, size); + message_buffer = itti_malloc (TASK_RRC_NRUE, TASK_RRC_GNB_SIM, size); memcpy (message_buffer, buffer, size); - message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, UE_RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_NRUE, UE_RRC_DCCH_DATA_IND); UE_RRC_DCCH_DATA_IND (message_p).rbid = 1; UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; UE_RRC_DCCH_DATA_IND (message_p).size = size; @@ -1394,84 +1404,85 @@ static void rrc_ue_generate_RRCSetupComplete( } int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB_INFO *const Srb_info, const uint8_t gNB_index ){ - NR_DL_CCCH_Message_t *dl_ccch_msg=NULL; - asn_dec_rval_t dec_rval; - int rval=0; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_IN); - // LOG_D(RRC,"[UE %d] Decoding DL-CCCH message (%d bytes), State %d\n",ue_mod_idP,Srb_info->Rx_buffer.payload_size, - // NR_UE_rrc_inst[ue_mod_idP].Info[gNB_index].State); - dec_rval = uper_decode(NULL, - &asn_DEF_NR_DL_CCCH_Message, - (void **)&dl_ccch_msg, - (uint8_t *)Srb_info->Rx_buffer.Payload, - 100,0,0); - - // if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { - xer_fprint(stdout,&asn_DEF_NR_DL_CCCH_Message,(void *)dl_ccch_msg); - // } - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed==0)) { - LOG_E(RRC,"[UE %d] Frame %d : Failed to decode DL-CCCH-Message (%zu bytes)\n",ctxt_pP->module_id,ctxt_pP->frame,dec_rval.consumed); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT); - return -1; - } - - if (dl_ccch_msg->message.present == NR_DL_CCCH_MessageType_PR_c1) { - if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State == NR_RRC_SI_RECEIVED) { - switch (dl_ccch_msg->message.choice.c1->present) { - case NR_DL_CCCH_MessageType__c1_PR_NOTHING: - LOG_I(NR_RRC, "[UE%d] Frame %d : Received PR_NOTHING on DL-CCCH-Message\n", - ctxt_pP->module_id, - ctxt_pP->frame); - rval = 0; - break; - - case NR_DL_CCCH_MessageType__c1_PR_rrcReject: - LOG_I(NR_RRC, - "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n", - ctxt_pP->module_id, - ctxt_pP->frame); - rval = 0; - break; - - case NR_DL_CCCH_MessageType__c1_PR_rrcSetup: - LOG_I(NR_RRC, - "[UE%d][RAPROC] Frame %d : Logical Channel DL-CCCH (SRB0), Received NR_RRCSetup RNTI %x\n", - ctxt_pP->module_id, - ctxt_pP->frame, - ctxt_pP->rnti); - // Get configuration - // Release T300 timer - NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T300_active = 0; - - nr_rrc_ue_process_masterCellGroup( - ctxt_pP, - gNB_index, - &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup); - nr_sa_rrc_ue_process_radioBearerConfig( - ctxt_pP, - gNB_index, - &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig); - nr_rrc_set_state (ctxt_pP->module_id, RRC_STATE_CONNECTED); - nr_rrc_set_sub_state (ctxt_pP->module_id, RRC_SUB_STATE_CONNECTED); - NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].rnti = ctxt_pP->rnti; - rrc_ue_generate_RRCSetupComplete( - ctxt_pP, - gNB_index, - dl_ccch_msg->message.choice.c1->choice.rrcSetup->rrc_TransactionIdentifier, - NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); - rval = 0; - break; - - default: - LOG_E(NR_RRC, "[UE%d] Frame %d : Unknown message\n", - ctxt_pP->module_id, - ctxt_pP->frame); - rval = -1; - break; + NR_DL_CCCH_Message_t *dl_ccch_msg=NULL; + asn_dec_rval_t dec_rval; + int rval=0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_IN); + // LOG_D(RRC,"[UE %d] Decoding DL-CCCH message (%d bytes), State %d\n",ue_mod_idP,Srb_info->Rx_buffer.payload_size, + // NR_UE_rrc_inst[ue_mod_idP].Info[gNB_index].State); + dec_rval = uper_decode(NULL, + &asn_DEF_NR_DL_CCCH_Message, + (void **)&dl_ccch_msg, + (uint8_t *)Srb_info->Rx_buffer.Payload, + 100,0,0); + + // if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout,&asn_DEF_NR_DL_CCCH_Message,(void *)dl_ccch_msg); + // } + + if ((dec_rval.code != RC_OK) && (dec_rval.consumed==0)) { + LOG_E(RRC,"[UE %d] Frame %d : Failed to decode DL-CCCH-Message (%zu bytes)\n",ctxt_pP->module_id,ctxt_pP->frame,dec_rval.consumed); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT); + return -1; + } + + if (dl_ccch_msg->message.present == NR_DL_CCCH_MessageType_PR_c1) { + if (NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].State == NR_RRC_SI_RECEIVED) { + switch (dl_ccch_msg->message.choice.c1->present) { + case NR_DL_CCCH_MessageType__c1_PR_NOTHING: + LOG_I(NR_RRC, "[UE%d] Frame %d : Received PR_NOTHING on DL-CCCH-Message\n", + ctxt_pP->module_id, + ctxt_pP->frame); + rval = 0; + break; + + case NR_DL_CCCH_MessageType__c1_PR_rrcReject: + LOG_I(NR_RRC, + "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n", + ctxt_pP->module_id, + ctxt_pP->frame); + rval = 0; + break; + + case NR_DL_CCCH_MessageType__c1_PR_rrcSetup: + LOG_I(NR_RRC, + "[UE%d][RAPROC] Frame %d : Logical Channel DL-CCCH (SRB0), Received NR_RRCSetup RNTI %x\n", + ctxt_pP->module_id, + ctxt_pP->frame, + ctxt_pP->rnti); + + // Get configuration + // Release T300 timer + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T300_active = 0; + + nr_rrc_ue_process_masterCellGroup( + ctxt_pP, + gNB_index, + &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup); + nr_sa_rrc_ue_process_radioBearerConfig( + ctxt_pP, + gNB_index, + &dl_ccch_msg->message.choice.c1->choice.rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig); + nr_rrc_set_state (ctxt_pP->module_id, RRC_STATE_CONNECTED); + nr_rrc_set_sub_state (ctxt_pP->module_id, RRC_SUB_STATE_CONNECTED); + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].rnti = ctxt_pP->rnti; + rrc_ue_generate_RRCSetupComplete( + ctxt_pP, + gNB_index, + dl_ccch_msg->message.choice.c1->choice.rrcSetup->rrc_TransactionIdentifier, + NR_UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); + rval = 0; + break; + + default: + LOG_E(NR_RRC, "[UE%d] Frame %d : Unknown message\n", + ctxt_pP->module_id, + ctxt_pP->frame); + rval = -1; + break; + } } } - } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT); return rval; @@ -1713,11 +1724,11 @@ nr_rrc_ue_process_securityModeCommand( #ifdef ITTI_SIM MessageDef *message_p; uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_UE_SIM,TASK_RRC_GNB_SIM, + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM, (enc_rval.encoded + 7) / 8); memcpy (message_buffer, buffer, (enc_rval.encoded + 7) / 8); - message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, UE_RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_NRUE, UE_RRC_DCCH_DATA_IND); GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_DCCH_DATA_IND (message_p).size = (enc_rval.encoded + 7) / 8; @@ -2252,6 +2263,7 @@ void nr_rrc_ue_generate_RRCReconfigurationComplete( const protocol_ctxt_t *const UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; UE_RRC_DCCH_DATA_IND (message_p).size = size; itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); + #else rrc_data_req_ue ( ctxt_pP, @@ -2320,32 +2332,38 @@ nr_rrc_ue_decode_dcch( nr_rrc_ue_generate_RRCReconfigurationComplete(ctxt_pP, gNB_indexP, dl_dcch_msg->message.choice.c1->choice.rrcReconfiguration->rrc_TransactionIdentifier); + + if (first_rrcreconfigurationcomplete == 0) { + first_rrcreconfigurationcomplete = 1; #ifdef ITTI_SIM - as_nas_info_t initialNasMsg; - memset(&initialNasMsg, 0, sizeof(as_nas_info_t)); - generateRegistrationComplete(&initialNasMsg, NULL); - if(initialNasMsg.length > 0){ - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_RRC_NRUE, NAS_UPLINK_DATA_REQ); - NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length; - itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p); - LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); - } - as_nas_info_t pduEstablishMsg; - memset(&pduEstablishMsg, 0, sizeof(as_nas_info_t)); - generatePduSessionEstablishRequest(&pduEstablishMsg); - if(initialNasMsg.length > 0){ - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_RRC_NRUE, NAS_UPLINK_DATA_REQ); - NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)pduEstablishMsg.data; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = pduEstablishMsg.length; - itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p); - LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); - } + if (AMF_MODE_ENABLED) { + as_nas_info_t initialNasMsg; + memset(&initialNasMsg, 0, sizeof(as_nas_info_t)); + generateRegistrationComplete(&initialNasMsg, NULL); + if(initialNasMsg.length > 0){ + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_RRC_NRUE, NAS_UPLINK_DATA_REQ); + NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length; + itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p); + LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); + } + as_nas_info_t pduEstablishMsg; + memset(&pduEstablishMsg, 0, sizeof(as_nas_info_t)); + generatePduSessionEstablishRequest(&pduEstablishMsg); + if(initialNasMsg.length > 0){ + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_RRC_NRUE, NAS_UPLINK_DATA_REQ); + NAS_UPLINK_DATA_REQ(message_p).UEid = ctxt_pP->module_id; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)pduEstablishMsg.data; + NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = pduEstablishMsg.length; + itti_send_msg_to_task(TASK_RRC_NRUE, ctxt_pP->instance, message_p); + LOG_I(NR_RRC, " Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); + } + } #endif + } } break; @@ -2375,6 +2393,14 @@ nr_rrc_ue_decode_dcch( gNB_indexP); break; case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment: + LOG_I(NR_RRC, + "[UE%d] Frame %d : Logical Channel DL-DCCH (SRB1), Received RRCReestablishment\n", + ctxt_pP->module_id, + ctxt_pP->frame); + nr_rrc_ue_generate_rrcReestablishmentComplete( + ctxt_pP, + dl_dcch_msg->message.choice.c1->choice.rrcReestablishment, + gNB_indexP); break; case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: { @@ -2515,8 +2541,8 @@ void *rrc_nrue_task( void *args_p ) { memcpy (srb_info_p->Rx_buffer.Payload, NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu, NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu_size); srb_info_p->Rx_buffer.payload_size = NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu_size; - // PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_NO, RRC_MAC_CCCH_DATA_IND (msg_p).rnti, RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0); - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, NR_RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0, NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index); + PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_NO, NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, NR_RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0); + // PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, NR_RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0, NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index); nr_rrc_ue_decode_ccch (&ctxt, srb_info_p, NR_RRC_MAC_CCCH_DATA_IND (msg_p).gnb_index); @@ -2706,11 +2732,11 @@ nr_rrc_ue_process_ueCapabilityEnquiry( #ifdef ITTI_SIM MessageDef *message_p; uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_UE_SIM,TASK_RRC_GNB_SIM, + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM, (enc_rval.encoded + 7) / 8); memcpy (message_buffer, buffer, (enc_rval.encoded + 7) / 8); - message_p = itti_alloc_new_message (TASK_RRC_UE_SIM, UE_RRC_DCCH_DATA_IND); + message_p = itti_alloc_new_message (TASK_RRC_NRUE, UE_RRC_DCCH_DATA_IND); GNB_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; GNB_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; GNB_RRC_DCCH_DATA_IND (message_p).size = (enc_rval.encoded + 7) / 8; @@ -2728,3 +2754,59 @@ nr_rrc_ue_process_ueCapabilityEnquiry( } } } + +//----------------------------------------------------------------------------- +void rrc_ue_generate_RRCReestablishmentRequest( const protocol_ctxt_t *const ctxt_pP, const uint8_t gNB_index ) +{ + NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size = + do_RRCReestablishmentRequest( + ctxt_pP->module_id, + (uint8_t *)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload, 1); + LOG_I(NR_RRC,"[UE %d] : Frame %d, Logical Channel UL-CCCH (SRB0), Generating RRCReestablishmentRequest (bytes %d, gNB %d)\n", + ctxt_pP->module_id, ctxt_pP->frame, NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size, gNB_index); + + for (int i=0; imodule_id].Srb0[gNB_index].Tx_buffer.payload_size; i++) { + LOG_T(NR_RRC,"%x.",NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload[i]); + } + + LOG_T(NR_RRC,"\n"); + +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM, + NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size); + memcpy (message_buffer, (uint8_t*)NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.Payload, + NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size); + message_p = itti_alloc_new_message (TASK_RRC_NRUE, UE_RRC_CCCH_DATA_IND); + UE_RRC_CCCH_DATA_IND (message_p).sdu = message_buffer; + UE_RRC_CCCH_DATA_IND (message_p).size = NR_UE_rrc_inst[ctxt_pP->module_id].Srb0[gNB_index].Tx_buffer.payload_size; + itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); +#endif +} + +void +nr_rrc_ue_generate_rrcReestablishmentComplete( + const protocol_ctxt_t *const ctxt_pP, + NR_RRCReestablishment_t *rrcReestablishment, + uint8_t gNB_index +) +//----------------------------------------------------------------------------- +{ + uint32_t length; + uint8_t buffer[100]; + length = do_RRCReestablishmentComplete(buffer, rrcReestablishment->rrc_TransactionIdentifier); +#ifdef ITTI_SIM + MessageDef *message_p; + uint8_t *message_buffer; + message_buffer = itti_malloc (TASK_RRC_NRUE,TASK_RRC_GNB_SIM,length); + memcpy (message_buffer, buffer, length); + + message_p = itti_alloc_new_message (TASK_RRC_NRUE, UE_RRC_DCCH_DATA_IND); + UE_RRC_DCCH_DATA_IND (message_p).rbid = DCCH; + UE_RRC_DCCH_DATA_IND (message_p).sdu = message_buffer; + UE_RRC_DCCH_DATA_IND (message_p).size = length; + itti_send_msg_to_task (TASK_RRC_GNB_SIM, ctxt_pP->instance, message_p); + +#endif +} diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index d9a291f5a3..8be356a90b 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -126,7 +126,6 @@ typedef struct NR_UE_RRC_INST_s { /* KeNB as computed from parameters within USIM card */ uint8_t kgnb[32]; - /* Used integrity/ciphering algorithms */ //RRC_LIST_TYPE(NR_SecurityAlgorithmConfig_t, NR_SecurityAlgorithmConfig) SecurityAlgorithmConfig_list; NR_CipheringAlgorithm_t cipheringAlgorithm; diff --git a/openair2/SIMULATION/NR_RRC/itti_sim.c b/openair2/SIMULATION/NR_RRC/itti_sim.c index 4fb784f84d..de72b764f2 100644 --- a/openair2/SIMULATION/NR_RRC/itti_sim.c +++ b/openair2/SIMULATION/NR_RRC/itti_sim.c @@ -104,7 +104,7 @@ int config_sync_var=-1; openair0_config_t openair0_cfg[MAX_CARDS]; -volatile int start_gNB = 0; +//volatile int start_gNB = 0; volatile int oai_exit = 0; //static int wait_for_sync = 0; @@ -543,7 +543,7 @@ int main( int argc, char **argv ) } AMF_MODE_ENABLED = !IS_SOFTMODEM_NOS1; - // AMF_MODE_ENABLED = 0; +// AMF_MODE_ENABLED = 0; NGAP_CONF_MODE = !IS_SOFTMODEM_NOS1; //!get_softmodem_params()->phy_test; #if T_TRACER diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index 4789efeebe..7e4f735705 100644 --- a/openair2/X2AP/x2ap_eNB.c +++ b/openair2/X2AP/x2ap_eNB.c @@ -310,14 +310,21 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, x2ap_register_eNB->t_dc_overall); for (int i = 0; i< x2ap_register_eNB->num_cc; i++) { - new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i]; - new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i]; + if(new_instance->cell_type == CELL_MACRO_GNB){ + new_instance->nr_band[i] = x2ap_register_eNB->nr_band[i]; + new_instance->tdd_nRARFCN[i] = x2ap_register_eNB->nrARFCN[i]; + } + else{ + new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i]; + new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i]; + new_instance->fdd_earfcn_DL[i] = x2ap_register_eNB->fdd_earfcn_DL[i]; + new_instance->fdd_earfcn_UL[i] = x2ap_register_eNB->fdd_earfcn_UL[i]; + } + new_instance->uplink_frequency_offset[i] = x2ap_register_eNB->uplink_frequency_offset[i]; new_instance->Nid_cell[i] = x2ap_register_eNB->Nid_cell[i]; new_instance->N_RB_DL[i] = x2ap_register_eNB->N_RB_DL[i]; new_instance->frame_type[i] = x2ap_register_eNB->frame_type[i]; - new_instance->fdd_earfcn_DL[i] = x2ap_register_eNB->fdd_earfcn_DL[i]; - new_instance->fdd_earfcn_UL[i] = x2ap_register_eNB->fdd_earfcn_UL[i]; } DevCheck(x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS, diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h index 3d8efd8cd4..063302d03a 100644 --- a/openair2/X2AP/x2ap_eNB_defs.h +++ b/openair2/X2AP/x2ap_eNB_defs.h @@ -179,6 +179,7 @@ typedef struct x2ap_eNB_instance_s { uint32_t specialSubframe[MAX_NUM_CCs]; //#ifdef Rel15 + int32_t nr_band[MAX_NUM_CCs]; uint32_t tdd_nRARFCN[MAX_NUM_CCs]; int16_t nr_SCS[MAX_NUM_CCs]; //#endif diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c index 1e549d8cbe..23973328f2 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.c +++ b/openair2/X2AP/x2ap_eNB_generate_messages.c @@ -39,7 +39,6 @@ #include "x2ap_ids.h" #include "x2ap_eNB_itti_messaging.h" -#include "X2AP_SupportedSULFreqBandItem.h" #include "msc.h" #include "assertions.h" @@ -1236,7 +1235,6 @@ int x2ap_gNB_generate_ENDC_x2_setup_request( X2AP_En_gNB_ENDCX2SetupReqIEs_t *ie_GNB_ENDC; X2AP_PLMN_Identity_t *plmn; ServedNRcellsENDCX2ManagementList__Member *servedCellMember; - X2AP_SupportedSULFreqBandItem_t *SULFreqBandItem; uint8_t *buffer; uint32_t len; @@ -1284,8 +1282,8 @@ MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length ie_GNB_ENDC->value.present = X2AP_En_gNB_ENDCX2SetupReqIEs__value_PR_ServedNRcellsENDCX2ManagementList; { - for (int i = 0; inum_cc; i++){ - servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)calloc(1,sizeof(ServedNRcellsENDCX2ManagementList__Member)); + for (int i = 0; inum_cc; i++){ + servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)calloc(1,sizeof(ServedNRcellsENDCX2ManagementList__Member)); { servedCellMember->servedNRCellInfo.nrpCI = instance_p->Nid_cell[i]; @@ -1299,60 +1297,63 @@ MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length NR_FIVEGS_TAC_ID_TO_BIT_STRING(instance_p->tac, servedCellMember->servedNRCellInfo.fiveGS_TAC); X2AP_INFO("TAC: %d -> %02x%02x%02x\n", instance_p->tac, - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], - servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t)); { MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn); ASN_SEQUENCE_ADD(&servedCellMember->servedNRCellInfo.broadcastPLMNs.list, plmn); } - - if (instance_p->frame_type[i] == TDD) { + if (instance_p->frame_type[i] == TDD) { X2AP_FreqBandNrItem_t *freq_band; servedCellMember->servedNRCellInfo.nrModeInfo.present = X2AP_ServedNRCell_Information__nrModeInfo_PR_tdd; - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.nRARFCN = 0; //instance_p->tdd_nRARFCN[i]; + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.nRARFCN = instance_p->tdd_nRARFCN[i]; /* addition of Frequency Band List */ freq_band = calloc(1, sizeof(X2AP_FreqBandNrItem_t)); if (freq_band == NULL) exit(1); - freq_band->freqBandIndicatorNr = instance_p->eutra_band[0]; - - SULFreqBandItem = calloc(1, sizeof(X2AP_SupportedSULFreqBandItem_t)); - SULFreqBandItem->freqBandIndicatorNr=80; /* TODO: put correct value */ - ASN_SEQUENCE_ADD(&freq_band->supportedSULBandList.list, SULFreqBandItem); + freq_band->freqBandIndicatorNr = instance_p->nr_band[i]; ASN_SEQUENCE_ADD(&servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.freqBandListNr, freq_band); switch (instance_p->N_RB_DL[i]) { - case 50: - //This is not correct. Just to be able to test X2 only using an eNB instead of gNB - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb51; + case 32: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb32; + break; + case 66: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb66; + break; + case 93 : + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb93; + break; + case 106: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb106; + break; + case 121: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb121; + break; + case 217: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb217; + break; + case 273: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb273; + break; + /*More cases to be added */ + default: + AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL"); break; - case 93 : - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb93; - break; - case 106: - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb106; - break; - case 121: - servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb121; - break; - /*More cases to be added */ - default: - AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL"); - break; - } - } + } + } else { AssertFatal(0,"ENDC_X2Setuprequest not supported for FDD!"); } - /*Don't know where to extract the value of measurementTimingConfiguration from. Set it to 0 for now */ - INT8_TO_OCTET_STRING(0, &servedCellMember->servedNRCellInfo.measurementTimingConfiguration); + /*Don't know where to extract the value of measurementTimingConfiguration from. Set it to 0 for now */ + INT8_TO_OCTET_STRING(0, &servedCellMember->servedNRCellInfo.measurementTimingConfiguration); } ASN_SEQUENCE_ADD(&ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list, servedCellMember); - } } + } ASN_SEQUENCE_ADD(&ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_en_gNB.list, ie_GNB_ENDC); @@ -1438,7 +1439,7 @@ int x2ap_eNB_generate_ENDC_x2_setup_response( } if (instance_p->frame_type[i] == FDD) { - servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD; servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i]; servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i]; switch (instance_p->N_RB_DL[i]) { @@ -1472,12 +1473,98 @@ int x2ap_eNB_generate_ENDC_x2_setup_response( } } else { - AssertFatal(0,"X2Setupresponse not supported for TDD!"); + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_tDD; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.eARFCN = instance_p->fdd_earfcn_DL[i]; + + switch (instance_p->subframeAssignment[i]) { + case 0: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa0; + break; + case 1: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa1; + break; + case 2: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa2; + break; + case 3: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa3; + break; + case 4: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa4; + break; + case 5: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa5; + break; + case 6: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.subframeAssignment = X2AP_SubframeAssignment_sa6; + break; + default: + AssertFatal(0,"Failed: Check value for subframeAssignment"); + break; + } + switch (instance_p->specialSubframe[i]) { + case 0: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp0; + break; + case 1: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp1; + break; + case 2: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp2; + break; + case 3: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp3; + break; + case 4: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp4; + break; + case 5: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp5; + break; + case 6: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp6; + break; + case 7: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp7; + break; + case 8: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.specialSubframePatterns = X2AP_SpecialSubframePatterns_ssp8; + break; + default: + AssertFatal(0,"Failed: Check value for subframeAssignment"); + break; + } + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.cyclicPrefixDL=X2AP_CyclicPrefixDL_normal; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.specialSubframe_Info.cyclicPrefixUL=X2AP_CyclicPrefixUL_normal; + + switch (instance_p->N_RB_DL[i]) { + case 6: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6; + break; + case 15: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15; + break; + case 25: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25; + break; + case 50: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50; + break; + case 75: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75; + break; + case 100: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.tDD.transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100; + break; + default: + AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL"); + break; + } } } - ASN_SEQUENCE_ADD(&ie_ENB_ENDC->value.choice.ServedEUTRAcellsENDCX2ManagementList.list, servedCellMember); + ASN_SEQUENCE_ADD(&ie_ENB_ENDC->value.choice.ServedEUTRAcellsENDCX2ManagementList.list, servedCellMember); } - } + } ASN_SEQUENCE_ADD(&ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_eNB.list, ie_ENB_ENDC); diff --git a/openair3/GTPV1-U/gtpv1u_gNB.c b/openair3/GTPV1-U/gtpv1u_gNB.c index 8d8a012437..4fde588e9f 100644 --- a/openair3/GTPV1-U/gtpv1u_gNB.c +++ b/openair3/GTPV1-U/gtpv1u_gNB.c @@ -551,6 +551,173 @@ gtpv1u_create_ngu_tunnel( return ret; } +int gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +) { + /* Local tunnel end-point identifier */ + teid_t ngu_teid = 0; + nr_gtpv1u_teid_data_t *gtpv1u_teid_data_p = NULL; + nr_gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; + nr_gtpv1u_ue_data_t *gtpv1u_ue_data_new_p = NULL; + //MessageDef *message_p = NULL; + hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; + int i,j; + uint8_t bearers_num = 0,bearers_total = 0; + //----------------------- + // PDCP->GTPV1U mapping + //----------------------- + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->ue_mapping, prior_rnti, (void **)>pv1u_ue_data_p); + + if(hash_rc != HASH_TABLE_OK) { + LOG_E(GTPU,"Error get ue_mapping(rnti=%x) from GTPV1U hashtable error\n", prior_rnti); + return -1; + } + + gtpv1u_ue_data_new_p = calloc (1, sizeof(nr_gtpv1u_ue_data_t)); + memcpy(gtpv1u_ue_data_new_p,gtpv1u_ue_data_p,sizeof(nr_gtpv1u_ue_data_t)); + gtpv1u_ue_data_new_p->ue_id = create_tunnel_req_pP->rnti; + hash_rc = hashtable_insert(RC.nr_gtpv1u_data_g->ue_mapping, create_tunnel_req_pP->rnti, gtpv1u_ue_data_new_p); + + //AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable"); + if ( hash_rc != HASH_TABLE_OK ) { + LOG_E(GTPU,"Failed to insert ue_mapping(rnti=%x) in GTPV1U hashtable\n",create_tunnel_req_pP->rnti); + return -1; + } else { + LOG_I(GTPU, "inserting ue_mapping(rnti=%x) in GTPV1U hashtable\n", + create_tunnel_req_pP->rnti); + } + + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->ue_mapping, prior_rnti); + LOG_I(GTPU, "hashtable_remove ue_mapping(rnti=%x) in GTPV1U hashtable\n", + prior_rnti); + //----------------------- + // GTPV1U->PDCP mapping + //----------------------- + bearers_total =gtpv1u_ue_data_new_p->num_bearers; + + for(j = 0; jbearers[j].state != BEARER_IN_CONFIG) + continue; + + bearers_num++; + + for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) { + if(j == (create_tunnel_req_pP->pdusession_id[i]-GTPV1U_BEARER_OFFSET)) + break; + } + + if(i < create_tunnel_req_pP->num_tunnels) { + ngu_teid = gtpv1u_ue_data_new_p->bearers[j].teid_gNB; + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid, (void **)>pv1u_teid_data_p); + + if (hash_rc == HASH_TABLE_OK) { + gtpv1u_teid_data_p->ue_id = create_tunnel_req_pP->rnti; + gtpv1u_teid_data_p->pdu_session_id = create_tunnel_req_pP->pdusession_id[i]; + LOG_I(GTPU, "updata teid_mapping te_id %u (prior_rnti %x rnti %x) in GTPV1U hashtable\n", + ngu_teid,prior_rnti,create_tunnel_req_pP->rnti); + } else { + LOG_W(GTPU, "Error get teid mapping(s1u_teid=%u) from GTPV1U hashtable", ngu_teid); + } + } else { + ngu_teid = gtpv1u_ue_data_new_p->bearers[j].teid_gNB; + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->teid_mapping, ngu_teid); + + if (hash_rc != HASH_TABLE_OK) { + LOG_D(GTPU, "Removed user rnti %x , enb S1U teid %u not found\n", prior_rnti, ngu_teid); + } + + gtpv1u_ue_data_new_p->bearers[j].state = BEARER_DOWN; + gtpv1u_ue_data_new_p->num_bearers--; + LOG_I(GTPU, "delete teid_mapping te_id %u (rnti%x) bearer_id %d in GTPV1U hashtable\n", + ngu_teid,prior_rnti,j+GTPV1U_BEARER_OFFSET);; + } + + if(bearers_num > bearers_total) + break; + } + + return 0; +} + +//----------------------------------------------------------------------------- +int gtpv1u_delete_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_delete_tunnel_req_t *const req_pP) { + NwGtpv1uUlpApiT stack_req; + NwGtpv1uRcT rc = NW_GTPV1U_FAILURE; + MessageDef *message_p = NULL; + nr_gtpv1u_ue_data_t *gtpv1u_ue_data_p = NULL; + hashtable_rc_t hash_rc = HASH_TABLE_KEY_NOT_EXISTS; + teid_t teid_gNB = 0; + int pdusession_index = 0; + message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_GNB_DELETE_TUNNEL_RESP); + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).rnti = req_pP->rnti; + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).status = 0; + hash_rc = hashtable_get(RC.nr_gtpv1u_data_g->ue_mapping, req_pP->rnti, (void **)>pv1u_ue_data_p); + + if (hash_rc == HASH_TABLE_OK) { + for (pdusession_index = 0; pdusession_index < req_pP->num_pdusession; pdusession_index++) { + teid_gNB = gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_gNB; + LOG_D(GTPU, "Rx GTPV1U_ENB_DELETE_TUNNEL user rnti %x eNB S1U teid %u eps bearer id %u\n", + req_pP->rnti, teid_gNB, req_pP->pdusession_id[pdusession_index]); + { + memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT)); + stack_req.apiType = NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT; + LOG_D(GTPU, "gtpv1u_delete_ngu_tunnel pdusession %u %u\n", + req_pP->pdusession_id[pdusession_index], + teid_gNB); + stack_req.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle = + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_gNB_stack_session; + rc = nwGtpv1uProcessUlpReq(RC.nr_gtpv1u_data_g->gtpv1u_stack, &stack_req); + LOG_D(GTPU, ".\n"); + } + + if (rc != NW_GTPV1U_OK) { + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).status |= 0xFF; + LOG_E(GTPU, "NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT failed"); + } + + //----------------------- + // PDCP->GTPV1U mapping + //----------------------- + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].state = BEARER_DOWN; + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_gNB = 0; + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].teid_upf = 0; + gtpv1u_ue_data_p->bearers[req_pP->pdusession_id[pdusession_index] - GTPV1U_BEARER_OFFSET].upf_ip_addr = 0; + gtpv1u_ue_data_p->num_bearers -= 1; + + if (gtpv1u_ue_data_p->num_bearers == 0) { + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->ue_mapping, req_pP->rnti); + LOG_D(GTPU, "Removed user rnti %x,no more bearers configured\n", req_pP->rnti); + } + + //----------------------- + // GTPV1U->PDCP mapping + //----------------------- + hash_rc = hashtable_remove(RC.nr_gtpv1u_data_g->teid_mapping, teid_gNB); + + if (hash_rc != HASH_TABLE_OK) { + LOG_D(GTPU, "Removed user rnti %x , gNB NGU teid %u not found\n", req_pP->rnti, teid_gNB); + } + } + }// else silently do nothing + + LOG_D(GTPU, "Tx GTPV1U_GNB_DELETE_TUNNEL_RESP user rnti %x gNB NGU teid %u status %u\n", + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).rnti, + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).gnb_NGu_teid, + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).status); + MSC_LOG_TX_MESSAGE( + MSC_GTPU_GNB, + MSC_RRC_GNB, + NULL,0, + "0 GTPV1U_GNB_DELETE_TUNNEL_RESP rnti %x teid %x", + GTPV1U_GNB_DELETE_TUNNEL_RESP(message_p).rnti, + teid_gNB); + return itti_send_msg_to_task(TASK_RRC_GNB, instanceP, message_p); +} + //----------------------------------------------------------------------------- static int gtpv1u_gNB_send_init_udp(const Gtpv1uNGReq *req) { // Create and alloc new message @@ -603,6 +770,10 @@ void *gtpv1u_gNB_process_itti_msg(void *notUsed) { gtpv1u_ng_req(instance, &received_message_p->ittiMsg.gtpv1uNGReq); break; + case GTPV1U_GNB_DELETE_TUNNEL_REQ: + gtpv1u_delete_ngu_tunnel(instance, &received_message_p->ittiMsg.NRGtpv1uDeleteTunnelReq); + break; + case TERMINATE_MESSAGE: { if (RC.nr_gtpv1u_data_g->ue_mapping != NULL) { hashtable_destroy (&(RC.nr_gtpv1u_data_g->ue_mapping)); diff --git a/openair3/GTPV1-U/gtpv1u_gNB_task.h b/openair3/GTPV1-U/gtpv1u_gNB_task.h index 5e16b0ed0c..fcfaa90304 100644 --- a/openair3/GTPV1-U/gtpv1u_gNB_task.h +++ b/openair3/GTPV1-U/gtpv1u_gNB_task.h @@ -40,5 +40,12 @@ gtpv1u_create_ngu_tunnel( const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP); +int +gtpv1u_update_ngu_tunnel( + const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + const rnti_t prior_rnti +); + #endif /* GTPV1U_GNB_TASK_H_ */ diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c index e0c207ce93..2c07de8dd5 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -525,6 +525,8 @@ void generateSecurityModeComplete(as_nas_info_t *initialNasMsg) } void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) { + //wait send RRCReconfigurationComplete and InitialContextSetupResponse + sleep(1); int length = 0; int size = 0; fgs_nas_message_t nas_msg; @@ -603,6 +605,8 @@ void generateRegistrationComplete(as_nas_info_t *initialNasMsg, SORTransparentCo } void generatePduSessionEstablishRequest(as_nas_info_t *initialNasMsg){ + //wait send RegistrationComplete + usleep(100*150); int size = 0; fgs_nas_message_t nas_msg; memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.h b/openair3/NAS/NR_UE/nr_nas_msg_sim.h index d5611c91a0..fef4671f43 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.h +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.h @@ -49,32 +49,13 @@ #define REGISTRATION_REQUEST 0b01000001 /* 65 = 0x41 */ #define REGISTRATION_ACCEPT 0b01000010 /* 66 = 0x42 */ #define REGISTRATION_COMPLETE 0b01000011 /* 67 = 0x43 */ -#define REGISTRATION_REJECT 0b01000100 /* 68 = 0x44 */ -#define DEREGISTRATION_REQUEST_UE_ORIGINATING 0b01000101 /* 69 = 0x45 */ -#define DEREGISTRATION_ACCEPT_UE_ORIGINATING 0b01000110 /* 70 = 0x46 */ -#define DEREGISTRATION_REQUEST_UE_TERMINATED 0b01000111 /* 71 = 0x47 */ -#define DEREGISTRATION_ACCEPT_UE_TERMINATED 0b01001000 /* 72 = 0x48 */ - -#define FIVEGMM_SERVICE_REQUEST 0b01001100 /* 76 = 0x4c */ -#define FIVEGMM_SERVICE_REJECT 0b01001101 /* 77 = 0x4d */ -#define FIVEGMM_SERVICE_ACCEPT 0b01001110 /* 78 = 0x4e */ -#define CONFIGURATION_UPDATE_COMMAND 0b01010100 /* 84 = 0x54 */ -#define CONFIGURATION_UPDATE_COMPLETE 0b01010101 /* 85 = 0x55 */ #define FGS_AUTHENTICATION_REQUEST 0b01010110 /* 86 = 0x56 */ #define FGS_AUTHENTICATION_RESPONSE 0b01010111 /* 87 = 0x57 */ -#define AUTHENTICATION_REJECT 0b01011000 /* 88 = 0x58 */ -#define AUTHENTICATION_FAILURE 0b01011001 /* 89 = 0x59 */ -#define AUTHENTICATION_RESULT 0b01011010 /* 90 = 0x5a */ #define FGS_IDENTITY_REQUEST 0b01011011 /* 91 = 0x5b */ #define FGS_IDENTITY_RESPONSE 0b01011100 /* 92 = 0x5c */ #define FGS_SECURITY_MODE_COMMAND 0b01011101 /* 93 = 0x5d */ #define FGS_SECURITY_MODE_COMPLETE 0b01011110 /* 94 = 0x5e */ -#define FIVEGMM_SECURITY_MODE_REJECT 0b01011111 /* 95 = 0x5f */ -#define FIVEGMM_STATUS 0b01100100 /* 100 = 0x64 */ -#define NOTIFICATION 0b01100101 /* 101 = 0x65 */ -#define NOTIFICATION_RESPONSE 0b01100110 /* 102 = 0x66 */ #define FGS_UPLINK_NAS_TRANSPORT 0b01100111 /* 103= 0x67 */ -#define DL_NAS_TRANSPORT 0b01101000 /* 104 = 0x68 */ // message type for 5GS session management #define FGS_PDU_SESSION_ESTABLISHMENT_REQ 0b11000001 /* 193= 0xc1 */ diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 6051e917b4..fe500d896b 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -1754,7 +1754,7 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, return 0; } -// handle e-rab release command and send it to rrc_end +// handle pdu session release command and send it to rrc_end static int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, uint32_t stream, @@ -1772,7 +1772,7 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, container = &pdu->choice.initiatingMessage->value.choice.PDUSessionResourceReleaseCommand; if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { - NGAP_ERROR("[SCTP %d] Received E-RAB release command for non existing AMF context\n", assoc_id); + NGAP_ERROR("[SCTP %d] Received pdu session release command for non existing AMF context\n", assoc_id); return -1; } @@ -1805,11 +1805,11 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, } /* Initial context request = UE-related procedure -> stream != 0 */ - if (stream == 0) { - NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n", - assoc_id, stream); - return -1; - } + // if (stream == 0) { + // NGAP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n", + // assoc_id, stream); + // return -1; + // } ue_desc_p->rx_stream = stream; @@ -1818,7 +1818,7 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); } - NGAP_DEBUG("[SCTP %d] Received E-RAB release command for gNB_UE_NGAP_ID %lu amf_ue_ngap_id %lu\n", + NGAP_DEBUG("[SCTP %d] Received pdu session release command for gNB_UE_NGAP_ID %lu amf_ue_ngap_id %lu\n", assoc_id, gnb_ue_ngap_id, amf_ue_ngap_id); message_p = itti_alloc_new_message(TASK_NGAP, NGAP_PDUSESSION_RELEASE_COMMAND); NGAP_PDUSESSION_RELEASE_COMMAND(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; @@ -1850,7 +1850,18 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, item_p = (NGAP_PDUSessionResourceToReleaseItemRelCmd_t *)ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i]; NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].pdusession_id = item_p->pDUSessionID; - NGAP_DEBUG("[SCTP] Received E-RAB release command for pDUSessionID id %ld\n", item_p->pDUSessionID); + if(item_p->pDUSessionResourceReleaseCommandTransfer.size > 0) { + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = item_p->pDUSessionResourceReleaseCommandTransfer.size; + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionResourceReleaseCommandTransfer.size); + memcpy(NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer, + item_p->pDUSessionResourceReleaseCommandTransfer.buf, + item_p->pDUSessionResourceReleaseCommandTransfer.size); + }else { + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = 0; + NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = NULL; + NGAP_ERROR("[NGAP] Received pdu session release command for pDUSessionResourceReleaseCommandTransfer is NULL!\n"); + } + NGAP_DEBUG("[NGAP] Received pdu session release command for pDUSessionID id %ld\n", item_p->pDUSessionID); } } else { return -1; diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 27afd1e397..4d87755e72 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -852,21 +852,22 @@ int ngap_gNB_initial_ctxt_resp( return -1; } - MSC_LOG_TX_MESSAGE( - MSC_NGAP_GNB, - MSC_NGAP_AMF, - (const char *)buffer, - length, - MSC_AS_TIME_FMT" InitialContextSetup successfulOutcome gNB_ue_ngap_id %u amf_ue_ngap_id %u", - 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), - initial_ctxt_resp_p->gNB_ue_ngap_id, - ue_context_p->amf_ue_ngap_id); - /* UE associated signalling -> use the allocated stream */ - ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, - ue_context_p->amf_ref->assoc_id, buffer, - length, ue_context_p->tx_stream); + MSC_LOG_TX_MESSAGE( + MSC_NGAP_GNB, + MSC_NGAP_AMF, + (const char *)buffer, + length, + MSC_AS_TIME_FMT" InitialContextSetup successfulOutcome gNB_ue_ngap_id %u amf_ue_ngap_id %u", + 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), + initial_ctxt_resp_p->gNB_ue_ngap_id, + ue_context_p->amf_ue_ngap_id); + /* UE associated signalling -> use the allocated stream */ + LOG_I(NR_RRC,"Send message to sctp: NGAP_InitialContextSetupResponse\n"); + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, buffer, + length, ue_context_p->tx_stream); - return 0; + return 0; } //------------------------------------------------------------------------------ @@ -1416,21 +1417,41 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ie->value.choice.RAN_UE_NGAP_ID = pdusession_release_resp_p->gNB_ue_ngap_id; ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); - /* optional */ - if (pdusession_release_resp_p->nb_of_pdusessions_released > 0) { - ie = (NGAP_PDUSessionResourceReleaseResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceReleaseResponseIEs_t)); - ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes; - ie->criticality = NGAP_Criticality_ignore; - ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes; + /* optional */ + if (pdusession_release_resp_p->nb_of_pdusessions_released > 0) { + ie = (NGAP_PDUSessionResourceReleaseResponseIEs_t *)calloc(1, sizeof(NGAP_PDUSessionResourceReleaseResponseIEs_t)); + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = NGAP_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes; - for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) { - NGAP_PDUSessionResourceReleasedItemRelRes_t *item; - item = (NGAP_PDUSessionResourceReleasedItemRelRes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceReleasedItemRelRes_t)); - - item->pDUSessionID = pdusession_release_resp_p->pdusession_release[i].pdusession_id; - NGAP_DEBUG("pdusession_release_resp: pdusession ID %ld\n", item->pDUSessionID); - ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceReleasedListRelRes.list, item); - } + for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) { + NGAP_PDUSessionResourceReleasedItemRelRes_t *item; + item = (NGAP_PDUSessionResourceReleasedItemRelRes_t *)calloc(1, sizeof(NGAP_PDUSessionResourceReleasedItemRelRes_t)); + + item->pDUSessionID = pdusession_release_resp_p->pdusession_release[i].pdusession_id; + if(pdusession_release_resp_p->pdusession_release[i].transfer_length > 0){ + item->pDUSessionResourceReleaseResponseTransfer.size = pdusession_release_resp_p->pdusession_release[i].transfer_length; + item->pDUSessionResourceReleaseResponseTransfer.buf = malloc(sizeof(uint8_t) * pdusession_release_resp_p->pdusession_release[i].transfer_length); + memcpy(item->pDUSessionResourceReleaseResponseTransfer.buf, + pdusession_release_resp_p->pdusession_release[i].transfer_buffer, + pdusession_release_resp_p->pdusession_release[i].transfer_length); + }else { + item->pDUSessionResourceReleaseResponseTransfer.size = 0; + item->pDUSessionResourceReleaseResponseTransfer.buf = NULL; + NGAP_DEBUG("pdusession_release_resp: transfer_buffer is NULL!\n"); +#ifdef ITTI_SIM + //For testing only + item->pDUSessionResourceReleaseResponseTransfer.buf = malloc(sizeof(uint8_t) * 1); + item->pDUSessionResourceReleaseResponseTransfer.size = 1; + uint8_t temp = 0; + memcpy(item->pDUSessionResourceReleaseResponseTransfer.buf, + &temp, + item->pDUSessionResourceReleaseResponseTransfer.size); +#endif + } + NGAP_DEBUG("pdusession_release_resp: pdusession ID %ld\n", item->pDUSessionID); + ASN_SEQUENCE_ADD(&ie->value.choice.PDUSessionResourceReleasedListRelRes.list, item); + } ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); } diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index 972bef0a07..ee006338c5 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -413,10 +413,16 @@ sctp_handle_new_association_req( } /* Subscribe to all events */ - memset((void *)&events, 1, sizeof(struct sctp_event_subscribe)); + events.sctp_data_io_event = 1; + events.sctp_association_event = 1; + events.sctp_address_event = 1; + events.sctp_send_failure_event = 1; + events.sctp_peer_error_event = 1; + events.sctp_shutdown_event = 1; + events.sctp_partial_delivery_event = 1; if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &events, - sizeof(struct sctp_event_subscribe)) < 0) { + 8) < 0) { SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n", strerror(errno)); close(sd); @@ -759,10 +765,16 @@ static int sctp_create_new_listener( } } - memset((void *)&event, 1, sizeof(struct sctp_event_subscribe)); + event.sctp_data_io_event = 1; + event.sctp_association_event = 1; + event.sctp_address_event = 1; + event.sctp_send_failure_event = 1; + event.sctp_peer_error_event = 1; + event.sctp_shutdown_event = 1; + event.sctp_partial_delivery_event = 1; if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &event, - sizeof(struct sctp_event_subscribe)) < 0) { + 8) < 0) { SCTP_ERROR("setsockopt: %s:%d\n", strerror(errno), errno); if (sd != -1) { close(sd); diff --git a/openair3/SCTP/sctp_primitives_client.c b/openair3/SCTP/sctp_primitives_client.c index bb71a854e1..e19f20c957 100644 --- a/openair3/SCTP/sctp_primitives_client.c +++ b/openair3/SCTP/sctp_primitives_client.c @@ -241,10 +241,16 @@ int sctp_connect_to_remote_host(char *local_ip_addr[], } /* Subscribe to all events */ - memset((void *)&events, 1, sizeof(struct sctp_event_subscribe)); + events.sctp_data_io_event = 1; + events.sctp_association_event = 1; + events.sctp_address_event = 1; + events.sctp_send_failure_event = 1; + events.sctp_peer_error_event = 1; + events.sctp_shutdown_event = 1; + events.sctp_partial_delivery_event = 1; if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &events, - sizeof(struct sctp_event_subscribe)) < 0) { + 8) < 0) { SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n", strerror(errno)); return -1; diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 3066f0906f..3a69d4c991 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -112,6 +112,9 @@ int load_lib(openair0_device *device, else deflibname=OAI_RF_LIBNAME; shlib_fdesc[0].fname="device_init"; + } else if (flag == RAU_REMOTE_THIRDPARTY_RADIO_HEAD) { + deflibname=OAI_THIRDPARTY_TP_LIBNAME; + shlib_fdesc[0].fname="transport_init"; } else { deflibname=OAI_TP_LIBNAME; shlib_fdesc[0].fname="transport_init"; diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 778c8165eb..85ee80ea7c 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -41,6 +41,8 @@ #define OAI_RF_LIBNAME "oai_device" /* name of shared library implementing the transport */ #define OAI_TP_LIBNAME "oai_transpro" +/* name of shared library implementing a third-party transport */ +#define OAI_THIRDPARTY_TP_LIBNAME "thirdparty_transpro" /* name of shared library implementing the rf simulator */ #define OAI_RFSIM_LIBNAME "rfsimulator" /* name of shared library implementing the basic simulator */ @@ -51,10 +53,9 @@ /* flags for BBU to determine whether the attached radio head is local or remote */ #define RAU_LOCAL_RADIO_HEAD 0 #define RAU_REMOTE_RADIO_HEAD 1 - +#define RAU_REMOTE_THIRDPARTY_RADIO_HEAD 2 #define MAX_WRITE_THREAD_PACKAGE 10 #define MAX_WRITE_THREAD_BUFFER_SIZE 8 - #ifndef MAX_CARDS #define MAX_CARDS 8 #endif @@ -367,12 +368,22 @@ struct openair0_device_t { /*! \brief Called to send samples to the RF target @param device pointer to the device structure specific to the RF hardware target @param timestamp The timestamp at whicch the first sample MUST be sent - @param buff Buffer which holds the samples + @param buff Buffer which holds the samples (2 dimensional) + @param nsamps number of samples to be sent + @param number of antennas + @param flags flags must be set to TRUE if timestamp parameter needs to be applied + */ + int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id, int flags); + + /*! \brief Called to send samples to the RF target + @param device pointer to the device structure specific to the RF hardware target + @param timestamp The timestamp at whicch the first sample MUST be sent + @param buff Buffer which holds the samples (1 dimensional) @param nsamps number of samples to be sent @param antenna_id index of the antenna if the device has multiple anteannas @param flags flags must be set to TRUE if timestamp parameter needs to be applied */ - int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id, int flags); + int (*trx_write_func2)(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int antenna_id, int flags); /*! \brief Receive samples from hardware. * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for @@ -382,10 +393,24 @@ struct openair0_device_t { * \param[out] ptimestamp the time at which the first sample was received. * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps. * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. - * \param antenna_id Index of antenna for which to receive samples + * \param num_antennas number of antennas from which to receive samples * \returns the number of sample read */ - int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int antenna_id); + + int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int num_antennas); + + /*! \brief Receive samples from hardware, this version provides a single antenna at a time and returns. + * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for + * the first channel. *ptimestamp is the time at which the first sample + * was received. + * \param device the hardware to use + * \param[out] ptimestamp the time at which the first sample was received. + * \param[out] buff A pointers to a buffer for received samples. The buffer must be large enough to hold the number of samples \ref nsamps. + * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. + * \param antenna_id Index of antenna from which samples were received + * \returns the number of sample read + */ + int (*trx_read_func2)(openair0_device *device, openair0_timestamp *ptimestamp, void *buff, int nsamps,int *antenna_id); /*! \brief print the device statistics * \param device the hardware to use @@ -431,6 +456,25 @@ struct openair0_device_t { */ void (*configure_rru)(int idx, void *arg); +/*! \brief Pointer to generic RRU private information + */ + + void *thirdparty_priv; + + /*! \brief Callback for Third-party RRU Initialization routine + \param device the hardware configuration to use + */ + int (*thirdparty_init)(openair0_device *device); + /*! \brief Callback for Third-party RRU Cleanup routine + \param device the hardware configuration to use + */ + int (*thirdparty_cleanup)(openair0_device *device); + + /*! \brief Callback for Third-party start streaming routine + \param device the hardware configuration to use + */ + int (*thirdparty_startstreaming)(openair0_device *device); + /*! \brief RRU Configuration callback * \param idx RU index * \param arg pointer to capabilities or configuration diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index d893c66b52..9c0a9e3f65 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -102,23 +102,15 @@ int eth_socket_init_raw(openair0_device *device) { eth->local_addrd_ll.sll_family = AF_PACKET; eth->local_addrd_ll.sll_ifindex = eth->if_index.ifr_ifindex; /* hear traffic from specific protocol*/ - if (eth->flags == ETH_RAW_IF5_MOBIPASS) { - eth->local_addrd_ll.sll_protocol = htons(0xbffe); - } else{ - eth->local_addrc_ll.sll_protocol = htons((short)device->eth_params->my_portc); - eth->local_addrd_ll.sll_protocol = htons((short)device->eth_params->my_portd); - } + eth->local_addrc_ll.sll_protocol = htons((short)device->eth_params->my_portc); + eth->local_addrd_ll.sll_protocol = htons((short)device->eth_params->my_portd); + eth->local_addrc_ll.sll_halen = ETH_ALEN; eth->local_addrc_ll.sll_pkttype = PACKET_OTHERHOST; eth->local_addrd_ll.sll_halen = ETH_ALEN; eth->local_addrd_ll.sll_pkttype = PACKET_OTHERHOST; eth->addr_len = sizeof(struct sockaddr_ll); - if ((eth->flags != ETH_RAW_IF5_MOBIPASS ) && - (bind(eth->sockfdc,(struct sockaddr *)ð->local_addrc_ll,eth->addr_len)<0)) { - perror("ETHERNET: Cannot bind to socket (control)"); - exit(0); - } if (bind(eth->sockfdd,(struct sockaddr *)ð->local_addrd_ll,eth->addr_len)<0) { perror("ETHERNET: Cannot bind to socket (user)"); exit(0); @@ -127,12 +119,9 @@ int eth_socket_init_raw(openair0_device *device) { /* Construct the Ethernet header */ ether_aton_r(local_mac, (struct ether_addr *)(&(eth->ehd.ether_shost))); ether_aton_r(remote_mac, (struct ether_addr *)(&(eth->ehd.ether_dhost))); - if (eth->flags == ETH_RAW_IF5_MOBIPASS) { - eth->ehd.ether_type = htons(0xbffe); - } else { - eth->ehc.ether_type = htons((short)device->eth_params->my_portc); - eth->ehd.ether_type = htons((short)device->eth_params->my_portd); - } + eth->ehc.ether_type = htons((short)device->eth_params->my_portc); + eth->ehd.ether_type = htons((short)device->eth_params->my_portd); + printf("[%s] binding to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"),eth->ehd.ether_shost[0],eth->ehd.ether_shost[1],eth->ehd.ether_shost[2],eth->ehd.ether_shost[3],eth->ehd.ether_shost[4],eth->ehd.ether_shost[5]); return 0; @@ -216,8 +205,6 @@ int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestam packet_size = RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks); } else if (flags == IF4p5_PULTICK) { packet_size = RAW_IF4p5_PULTICK_SIZE_BYTES; - } else if (flags == IF5_MOBIPASS) { - packet_size = RAW_IF5_MOBIPASS_SIZE_BYTES; } else { packet_size = RAW_IF4p5_PRACH_SIZE_BYTES; } @@ -430,53 +417,6 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam } -int trx_eth_read_raw_IF5_mobipass(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { - // Read nblocks info from packet itself - - int bytes_received=0; - eth_state_t *eth = (eth_state_t*)device->priv; - int ret; - - ssize_t packet_size = 28; //MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t ; -// ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 640*sizeof(int16_t); - - bytes_received = recv(eth->sockfdd, - buff[0], - packet_size, - MSG_PEEK); - - if (bytes_received ==-1) { - eth->num_rx_errors++; - perror("[MOBIPASS]ETHERNET IF5 READ (header): "); - exit(-1); - } - - IF5_mobipass_header_t *test_header = (IF5_mobipass_header_t*)((uint8_t *)buff[0] + MAC_HEADER_SIZE_BYTES); - *timestamp = test_header->time_stamp; - packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF5_mobipass_header_t + 640*sizeof(int16_t); - - while(bytes_received < packet_size) { - ret = recv(eth->sockfdd, - buff[0], - packet_size, - 0); - if (bytes_received ==-1) { - eth->num_rx_errors++; - perror("[MOBIPASS] ETHERNET IF5 READ (payload): "); - return(-1); - } else { - bytes_received+=ret; - eth->rx_actual_nsamps = bytes_received>>1; - eth->rx_count++; - } - } - - eth->rx_nsamps = nsamps; - return(bytes_received); - - -} - int eth_set_dev_conf_raw(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index 473d129aaf..2dfb4a7bf1 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -47,7 +47,7 @@ #include "ethernet_lib.h" #include "common/ran_context.h" -#define DEBUG 0 +//#define DEBUG 1 // These are for IF5 and must be put into the device structure if multiple RUs in the same RAU !!!!!!!!!!!!!!!!! uint16_t pck_seq_num = 1; @@ -142,8 +142,8 @@ int eth_socket_init_udp(openair0_device *device) { perror("ETHERNET: Cannot set SO_REUSEADDR option on socket (control)"); exit(0); } - if (setsockopt(eth->sockfdd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int))) { - perror("ETHERNET: Cannot set SO_REUSEADDR option on socket (user)"); + if (setsockopt(eth->sockfdd, SOL_SOCKET, SO_NO_CHECK, &enable, sizeof(int))) { + perror("ETHERNET: Cannot set SO_NO_CHECK option on socket (user)"); exit(0); } @@ -202,8 +202,9 @@ int trx_eth_read_udp_IF4p5(openair0_device *device, openair0_timestamp *timestam goto again; } } else { - perror("ETHERNET IF4p5 READ"); - printf("(%s):\n", strerror(errno)); + return(-1); + //perror("ETHERNET IF4p5 READ"); + //printf("(%s):\n", strerror(errno)); } } else { *timestamp = test_header->sub_type; @@ -264,36 +265,82 @@ int trx_eth_write_udp_IF4p5(openair0_device *device, openair0_timestamp timestam return (bytes_sent); } -int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) { +int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int cc, int flags) { int bytes_sent=0; eth_state_t *eth = (eth_state_t*)device->priv; int sendto_flag =0; - int i=0; + //sendto_flag|=flags; eth->tx_nsamps=nsamps; - for (i=0;i>3; + __m256i buff_tx[nsamps2+1]; + __m256i *buff_tx2=buff_tx+1; +#else + nsamps2 = (nsamps+3)>>2; + __m128i buff_tx[nsamps2+2]; + __m128i *buff_tx2=buff_tx+2; +#endif +#elif defined(__arm__) || defined(__aarch64__) + nsamps2 = (nsamps+3)>>2; + int16x8_t buff_tx[nsamps2+2]; + int16x8_t *buff_tx2=buff_tx+2; +#else +#error Unsupported CPU architecture, ethernet device cannot be built +#endif + + + // bring TX data into 12 LSBs for softmodem RX + for (int j=0; jpck_header.seq_num = pck_seq_num; - //eth->pck_header.antenna_id = 1+(i<<1); - //eth->pck_header.timestamp = timestamp; - *(uint16_t *)buff2 = eth->pck_seq_num; - *(uint16_t *)(buff2 + sizeof(uint16_t)) = 1+(i<<1); - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_SEQ_NUM, eth->pck_seq_num); + // ECPRI Protocol revision + reserved bits (1 byte) + *(uint8_t *)buff2 = ECPRIREV; + // ECPRI Message type (1 byte) + *(uint8_t *)(buff2 + 1) = 64; + // ECPRI Payload Size (2 bytes) + AssertFatal(nsamps<16381,"nsamps > 16381\n"); + *(uint8_t *)(buff2 + 2) = (nsamps<<2)>>8; + *(uint8_t *)(buff2 + 3) = (nsamps<<2)&0xff; + // ECPRI PC_ID (2 bytes) + *(uint16_t *)(buff2 + 4) = cc; + // OAI modified SEQ_ID (4 bytes) + *(uint64_t *)(buff2 + 6) = ((uint64_t )timestamp)*6; + + /* + printf("ECPRI TX (REV %x, MessType %d, Payload size %d, PC_ID %d, TS %llu\n", + *(uint8_t *)buff2, + *(uint8_t *)(buff2+1), + *(uint16_t *)(buff2+2), + *(uint16_t *)(buff2+4), + *(uint64_t *)(buff2+6)); + */ int sent_byte; if (eth->compression == ALAW_COMPRESS) { @@ -311,7 +358,7 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi bytes_sent); #endif /* Send packet */ - bytes_sent += sendto(eth->sockfdd, + bytes_sent = sendto(eth->sockfdd, buff2, sent_byte, sendto_flag, @@ -339,17 +386,13 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi } //} - /* tx buffer values restored */ - *(int32_t *)buff2 = temp0; - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; - } - return (bytes_sent-APP_HEADER_SIZE_BYTES)>>2; } +#define NOSHIFT 1 -int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { +int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void *buff, int nsamps, int *cc) { int bytes_received=0; eth_state_t *eth = (eth_state_t*)device->priv; @@ -357,105 +400,98 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, voi int rcvfrom_flag =0; int block_cnt=0; int again_cnt=0; - int i=0; + static int packet_cnt=0; + int payload_size = UDP_PACKET_SIZE_BYTES(nsamps); +#if defined(__x86_64__) || defined(__i386__) +#ifdef __AVX2__ + int nsamps2 = (payload_size>>5)+1; + __m256i temp_rx[nsamps2]; + char *temp_rx0 = ((char *)&temp_rx[1])-APP_HEADER_SIZE_BYTES; +#else + int nsamps2 = (payload_size>>4)+1; + __m128i temp_rx[nsamps2]; + char *temp_rx0 = ((char *)&temp_rx[1])-APP_HEADER_SIZE_BYTES; +#endif +#elif defined(__arm__) || defined(__aarch64__) + int nsamps2 = (payload_size>>4)+1 + int16x8_t temp_rx[nsamps2]; + char *temp_rx0 = ((char *)&temp_rx[1])-APP_HEADER_SIZE_BYTES; +#else +#error Unsupported CPU architecture device cannot be built + int nsamps2 = (payload_size>>2)+1; + int32_t temp_rx[payload_size>>2]; + char* *temp_rx0 = ((char *)&temp_rx[1]) - APP_HEADER_SIZE_BYTES; +#endif + eth->rx_nsamps=nsamps; - for (i=0;icompression == ALAW_COMPRESS) { - receive_bytes = UDP_PACKET_SIZE_BYTES_ALAW(nsamps); - } else { - receive_bytes = UDP_PACKET_SIZE_BYTES(nsamps); - } - - while(bytes_received < receive_bytes) { - again: -#if DEBUG - printf("------- RX------: buff2 current position=%d remaining_bytes=%d bytes_recv=%d \n", - (void *)(buff2+bytes_received), - receive_bytes - bytes_received, - bytes_received); -#endif - bytes_received +=recvfrom(eth->sockfdd, - buff2, - receive_bytes, - rcvfrom_flag, - (struct sockaddr *)ð->dest_addrd, - (socklen_t *)ð->addr_len); - - if (bytes_received ==-1) { - eth->num_rx_errors++; - if (errno == EAGAIN) { - again_cnt++; - usleep(10); - if (again_cnt == 1000) { + bytes_received=0; + block_cnt=0; + AssertFatal(eth->compression == NO_COMPRESS, "IF5 compression not supported for now\n"); + + while(bytes_received < payload_size) { + again: + bytes_received +=recvfrom(eth->sockfdd, + temp_rx0, + payload_size, + rcvfrom_flag, + (struct sockaddr *)ð->dest_addrd, + (socklen_t *)ð->addr_len); + packet_cnt++; + if (bytes_received ==-1) { + eth->num_rx_errors++; + if (errno == EAGAIN) { + again_cnt++; + usleep(10); + if (again_cnt == 1000) { perror("ETHERNET READ: "); exit(-1); - } else { - printf("AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN \n"); - goto again; - } - } else if (errno == EWOULDBLOCK) { - block_cnt++; - usleep(10); - if (block_cnt == 1000) { - perror("ETHERNET READ: "); - exit(-1); - } else { - printf("BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK \n"); - goto again; - } + } else { + bytes_received=0; + goto again; + } + } else if (errno == EWOULDBLOCK) { + block_cnt++; + usleep(10); + if (block_cnt == 1000) { + perror("ETHERNET READ: "); + exit(-1); + } else { + printf("BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK \n"); + goto again; } - } else { -#if DEBUG - printf("------- RX------: nu=%d an_id=%d ts%d bytes_recv=%d\n", - *(int16_t *)buff2, - *(int16_t *)(buff2 + sizeof(int16_t)), - *(openair0_timestamp *)(buff2 + sizeof(int32_t)), - bytes_received); - - dump_packet((device->host_type == RAU_HOST)? "RAU":"RRU", buff2, UDP_PACKET_SIZE_BYTES(nsamps),RX_FLAG); -#endif - - /* store the timestamp value from packet's header */ - *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); - /* store the sequence number of the previous packet received */ - if (eth->pck_seq_num_cur == 0) { - eth->pck_seq_num_prev = *(uint16_t *)buff2; - } else { - eth->pck_seq_num_prev = eth->pck_seq_num_cur; - } - /* get the packet sequence number from packet's header */ - eth->pck_seq_num_cur = *(uint16_t *)buff2; - if ( ( eth->pck_seq_num_cur != (eth->pck_seq_num_prev + 1) ) && !((eth->pck_seq_num_prev==MAX_PACKET_SEQ_NUM(nsamps,device->openair0_cfg->samples_per_frame)) && (eth->pck_seq_num_cur==1 )) && !((eth->pck_seq_num_prev==1) && (eth->pck_seq_num_cur==1))) { - //#if DEBUG - printf("Out of order packet received: current_packet=%d previous_packet=%d timestamp=%"PRId64"\n",eth->pck_seq_num_cur,eth->pck_seq_num_prev,*timestamp); - //#endif - } - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM,eth->pck_seq_num_cur); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV,eth->pck_seq_num_prev); - eth->rx_actual_nsamps=bytes_received>>2; - eth->rx_count++; - } - } - /* tx buffer values restored */ - *(int32_t *)buff2 = temp0; - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; - - } - return (bytes_received-APP_HEADER_SIZE_BYTES)>>2; + } else { + /* store the timestamp value from packet's header */ + *timestamp = *(openair0_timestamp *)(temp_rx0 + ECPRICOMMON_BYTES+ECPRIPCID_BYTES); + // convert TS to samples, /3 for 30.72 Ms/s, /6 for 15.36 Ms/s, /12 for 7.68 Ms/s, etc. + *timestamp = *timestamp/6; + // handle 1.4,3,5,10,15 MHz cases + *cc = *(uint16_t*)(temp_rx0 + ECPRICOMMON_BYTES); + } + eth->rx_actual_nsamps=payload_size>>2; + eth->rx_count++; + } + +#ifdef NOSHIFT + memcpy(buff,(void*)(temp_rx+1),payload_size); +#else + // populate receive buffer in lower 12-bits from 16-bit representation + for (int j=1; j>2); } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 1d3c280f0e..dce410de47 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -52,11 +52,20 @@ int num_devices_eth = 0; struct sockaddr_in dest_addr[MAX_INST]; int dest_addr_len[MAX_INST]; +int load_lib(openair0_device *device, + openair0_config_t *openair0_cfg, + eth_params_t *cfg, + uint8_t flag); int trx_eth_start(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; + if (eth->flags == ETH_UDP_IF5_ECPRI_MODE) { + AssertFatal(device->thirdparty_init != NULL, "device->thirdparty_init is null\n"); + AssertFatal(device->thirdparty_init(device) == 0, "third-party init failed\n"); + device->openair0_cfg->samples_per_packet = 256; + } /* initialize socket */ if (eth->flags == ETH_RAW_MODE) { printf("Setting ETHERNET to ETH_RAW_IF5_MODE\n"); @@ -121,11 +130,6 @@ int trx_eth_start(openair0_device *device) - } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { - printf("Setting ETHERNET to RAW_IF5_MODE\n"); - if (eth_socket_init_raw(device)!=0) return -1; - if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; - } else { printf("Setting ETHERNET to UDP_IF5_MODE\n"); if (eth_socket_init_udp(device)!=0) return -1; @@ -137,8 +141,7 @@ int trx_eth_start(openair0_device *device) if(eth_get_dev_conf_udp(device)!=0) return -1; }*/ - /* adjust MTU wrt number of samples per packet */ - if(ethernet_tune (device,MTU_SIZE,UDP_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; + //if(ethernet_tune (device,MTU_SIZE,UDP_IF4p5_PRACH_SIZE_BYTES)!=0) return -1; if(ethernet_tune (device,RCV_TIMEOUT,999999)!=0) return -1; } @@ -166,9 +169,15 @@ void trx_eth_end(openair0_device *device) } -int trx_eth_stop(openair0_device *device) -{ - return(0); + +int trx_eth_stop(openair0_device *device) { + eth_state_t *eth = (eth_state_t*)device->priv; + + if (eth->flags == ETH_UDP_IF5_ECPRI_MODE) { + AssertFatal(device->thirdparty_cleanup != NULL, "device->thirdparty_cleanup is null\n"); + AssertFatal(device->thirdparty_cleanup(device) == 0, "third-party cleanup failed\n"); + } + return(0); } @@ -387,20 +396,11 @@ int transport_init(openair0_device *device, eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t)); memset(eth, 0, sizeof(eth_state_t)); - if (eth_params->transp_preference == 1) { - eth->flags = ETH_RAW_MODE; - } else if (eth_params->transp_preference == 0) { - eth->flags = ETH_UDP_MODE; - } else if (eth_params->transp_preference == 3) { - eth->flags = ETH_RAW_IF4p5_MODE; - } else if (eth_params->transp_preference == 2) { - eth->flags = ETH_UDP_IF4p5_MODE; - } else if (eth_params->transp_preference == 4) { - eth->flags = ETH_RAW_IF5_MOBIPASS; - } else { - printf("transport_init: Unknown transport preference %d - default to RAW", eth_params->transp_preference); - eth->flags = ETH_RAW_MODE; - } + eth->flags = eth_params->transp_preference; + + // load third-party driver + if (eth->flags == ETH_UDP_IF5_ECPRI_MODE) load_lib(device,openair0_cfg,eth_params,RAU_REMOTE_THIRDPARTY_RADIO_HEAD); + if (eth_params->if_compress == 0) { eth->compression = NO_COMPRESS; @@ -423,12 +423,17 @@ int transport_init(openair0_device *device, device->trx_set_gains_func = trx_eth_set_gains; device->trx_write_init = trx_eth_write_init; - if (eth->flags == ETH_RAW_MODE) { + device->trx_read_func2 = NULL; + device->trx_read_func = NULL; + device->trx_write_func2 = NULL; + device->trx_write_func = NULL; + + if (eth->flags == ETH_RAW_MODE) { device->trx_write_func = trx_eth_write_raw; device->trx_read_func = trx_eth_read_raw; - } else if (eth->flags == ETH_UDP_MODE) { - device->trx_write_func = trx_eth_write_udp; - device->trx_read_func = trx_eth_read_udp; + } else if (eth->flags == ETH_UDP_MODE || eth->flags == ETH_UDP_IF5_ECPRI_MODE) { + device->trx_write_func2 = trx_eth_write_udp; + device->trx_read_func2 = trx_eth_read_udp; device->trx_ctlsend_func = trx_eth_ctlsend_udp; device->trx_ctlrecv_func = trx_eth_ctlrecv_udp; } else if (eth->flags == ETH_RAW_IF4p5_MODE) { @@ -439,9 +444,6 @@ int transport_init(openair0_device *device, device->trx_read_func = trx_eth_read_udp_IF4p5; device->trx_ctlsend_func = trx_eth_ctlsend_udp; device->trx_ctlrecv_func = trx_eth_ctlrecv_udp; - } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) { - device->trx_write_func = trx_eth_write_raw_IF4p5; - device->trx_read_func = trx_eth_read_raw_IF5_mobipass; } else { //device->trx_write_func = trx_eth_write_udp_IF4p5; //device->trx_read_func = trx_eth_read_udp_IF4p5; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index 65b2def60d..ad64ac1a8a 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -49,7 +49,10 @@ #define RX_FLAG 0 #include "if_defs.h" -#define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp)) +#define ECPRICOMMON_BYTES 4 +#define ECPRIPCID_BYTES 2 +#define APP_HEADER_SIZE_BYTES (ECPRICOMMON_BYTES + ECPRIPCID_BYTES + sizeof(openair0_timestamp)) +#define ECPRIREV 1 // ECPRI Version 1, C=0 - single ECPRI message per OAI TX packet /*!\brief opaque ethernet data structure */ typedef struct { @@ -234,8 +237,8 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value); * @ingroup _oai */ int eth_socket_init_udp(openair0_device *device); -int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); -int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int cc, int flags); +int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void *buff, int nsamps, int *cc); int eth_socket_init_raw(openair0_device *device); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h index 0f2147847a..47205cf8b8 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h @@ -36,15 +36,17 @@ #include #include +#ifndef LITE_COMPILATION #include "PHY/LTE_TRANSPORT/if4_tools.h" #include "PHY/LTE_TRANSPORT/if5_tools.h" +#endif // ETH transport preference modes -#define ETH_UDP_MODE 0 -#define ETH_RAW_MODE 1 +#define ETH_UDP_MODE 0 +#define ETH_RAW_MODE 1 #define ETH_UDP_IF4p5_MODE 2 #define ETH_RAW_IF4p5_MODE 3 -#define ETH_RAW_IF5_MOBIPASS 4 +#define ETH_UDP_IF5_ECPRI_MODE 4 // COMMOM HEADER LENGTHS diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf index ea38aba1b2..19d9146f34 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf @@ -71,6 +71,11 @@ gNBs = initialDLBWPmappingType_2 = 0; #this is SS=1,L=12 initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) + initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; #uplinkConfigCommon #frequencyInfoUL ul_frequencyBand = 257; @@ -89,7 +94,7 @@ gNBs = initialULBWPsubcarrierSpacing = 3; #rach-ConfigCommon #rach-ConfigGeneric - prach_ConfigurationIndex = 98; + prach_ConfigurationIndex = 52; #prach_msg1_FDM #0 = one, 1=two, 2=four, 3=eight prach_msg1_FDM = 0; @@ -103,12 +108,12 @@ gNBs = powerRampingStep = 1; #ra_ReponseWindow #1,2,4,8,10,20,40,80 - ra_ResponseWindow = 4; + ra_ResponseWindow = 7; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR -#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen +#0=oneeighth,1=onefourth,2=half,3=one,4=two,5=four,6=eight,7=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; #oneHalf (0..15) 4,8,12,16,...60,64 - ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 7; #ra_ContentionResolutionTimer #(0..7) 8,16,24,32,40,48,56,64 ra_ContentionResolutionTimer = 7; @@ -119,22 +124,26 @@ gNBs = 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, + msg1_SubcarrierSpacing = 3, # restrictedSetConfig # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; + initialULBWPk2_0 = 6; initialULBWPmappingType_0 = 1 # this is SS=0 L=11 initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; + + initialULBWPk2_1 = 6; initialULBWPmappingType_1 = 1; # this is SS=0 L=12 initialULBWPstartSymbolAndLength_1 = 69; + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; msg3_DeltaPreamble = 1; p0_NominalWithGrant =-90; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf index 82b941ea0e..6681a43a1d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf @@ -47,7 +47,7 @@ gNBs = dl_carrierBandwidth = 32; #initialDownlinkBWP #genericParameters - # this is RBstart=0,L=50 (275*(L-1))+RBstart + # this is RBstart=0,L=32 (275*(L-1))+RBstart initialDLBWPlocationAndBandwidth = 8525; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 @@ -121,8 +121,8 @@ gNBs = ra_ContentionResolutionTimer = 7; rsrp_ThresholdSSB = 19; #prach-RootSequenceIndex_PR -#0 = 839, 1 = 139 - prach_RootSequenceIndex_PR = 1; +#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 # @@ -132,12 +132,12 @@ gNBs = # 0=unrestricted, 1=restricted type A, 2=restricted type B restrictedSetConfig = 0, # pusch-ConfigCommon (up to 16 elements) - initialULBWPk2_0 = 2; + initialULBWPk2_0 = 6; initialULBWPmappingType_0 = 1 # this is SS=0 L=11 initialULBWPstartSymbolAndLength_0 = 55; - - initialULBWPk2_1 = 2; + + initialULBWPk2_1 = 6; initialULBWPmappingType_1 = 1; # this is SS=0 L=12 initialULBWPstartSymbolAndLength_1 = 69; @@ -211,7 +211,7 @@ gNBs = ); ///X2 - enable_x2 = "yes"; + enable_x2 = "no"; t_reloc_prep = 1000; /* unit: millisecond */ tx2_reloc_overall = 2000; /* unit: millisecond */ t_dc_prep = 1000; /* unit: millisecond */ diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index 56078029af..1cd3b01b6c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -1,6 +1,7 @@ Active_gNBs = ( "gNB-Eurecom-5GNRBox"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; +Num_Threads_PUSCH = 8; gNBs = ( diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc_b38_if5_ENDC.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc_b38_if5_ENDC.conf new file mode 100644 index 0000000000..9b611b3f07 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc_b38_if5_ENDC.conf @@ -0,0 +1,243 @@ +Active_eNBs = ( "eNB_Eurecom_VCO_B38"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_VCO_B38"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + + plmn_list = ( { mcc = 222; mnc = 01; mnc_length = 2; } ); + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "NGFI_RCC_IF5"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + frame_type = "TDD"; + tdd_config = 1; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 38; + downlink_frequency = 2585000000L; + uplink_frequency_offset = 0; + Nid_cell = 0; + N_RB_DL = 100; + Nid_cell_mbsfn = 0; + nb_antenna_ports = 1; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 5; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = 10; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -106; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + ue_TransmissionMode = 1; + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.18.150"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + enable_measurement_reports = "no"; + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + t_dc_prep = 1000; + t_dc_overall = 2000; + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "bond0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.18.203/24"; + ENB_INTERFACE_NAME_FOR_S1U = "bond0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.18.203/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "192.168.18.203/24"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + + log_config : + { + global_log_level ="debug"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + scheduler_mode = "fairRR"; + puSch10xSnr = 100; + puCch10xSnr = 100; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 150; + } +); + +RUs = ( + { + local_if_name = "bond0"; + remote_address = "192.168.18.222"; + local_address = "192.168.18.203"; + local_portc = 50000; + remote_portc = 55444; + local_portd = 52001; + remote_portd = 52183; + local_rf = "no" + tr_preference = "udp_ecpri_if5" + nb_tx = 1 + nb_rx = 1 + att_tx = 5 + att_rx = 0; + eNB_instances = [0]; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +NETWORK_CONTROLLER : +{ + FLEXRAN_ENABLED = "no"; + FLEXRAN_INTERFACE_NAME = "lo"; + FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; + FLEXRAN_PORT = 2210; + FLEXRAN_CACHE = "/mnt/oai_agent_cache"; + FLEXRAN_AWAIT_RECONF = "no"; +}; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf index fd1b62fd3d..e34b261500 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf @@ -1,6 +1,7 @@ Active_gNBs = ( "gNB-Eurecom-5GNRBox"); # Asn1_verbosity, choice in: none, info, annoying Asn1_verbosity = "none"; +Num_Threads_PUSCH = 8; gNBs = ( diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 7d6cb9c429..1347d75fb0 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -461,10 +461,9 @@ void eNB_top(PHY_VARS_eNB *eNB, L1_proc->subframe_rx = ru_proc->tti_rx; L1_proc->frame_tx = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; L1_proc->subframe_tx = (L1_proc->subframe_rx + sf_ahead)%10; - + if (rxtx(eNB,L1_proc,string) < 0) - LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); - + LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); ru_proc->timestamp_tx = L1_proc->timestamp_tx; ru_proc->tti_tx = L1_proc->subframe_tx; ru_proc->frame_tx = L1_proc->frame_tx; @@ -1168,6 +1167,7 @@ void init_eNB_afterRU(void) { for (ru_id=0,aa=0; ru_idnum_RU; ru_id++) { eNB->frame_parms.nb_antennas_rx += eNB->RU_list[ru_id]->nb_rx; + AssertFatal(eNB->RU_list[ru_id]->common.rxdataF!=NULL, "RU %d : common.rxdataF is NULL\n", eNB->RU_list[ru_id]->idx); diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index e3b9797105..56c2cb23dd 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -120,6 +120,8 @@ void configure_rru(int idx, void reset_proc(RU_t *ru); int connect_rau(RU_t *ru); +void wait_eNBs(void); + const char ru_states[6][9] = {"RU_IDLE","RU_CONFIG","RU_READY","RU_RUN","RU_ERROR","RU_SYNC"}; extern uint16_t sf_ahead; @@ -141,16 +143,12 @@ extern uint16_t sf_ahead; static inline void fh_if5_south_out(RU_t *ru,int frame, int subframe, uint64_t timestamp) { if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); + ru->south_out_cnt++; + send_IF5(ru, timestamp, subframe, &ru->seqno, IF5_RRH_GW_DL); } -// southbound IF5 fronthaul for Mobipass packet format -static inline void fh_if5_mobipass_south_out(RU_t *ru,int frame, int subframe, uint64_t timestamp) { - if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); - - send_IF5(ru, timestamp, subframe, &ru->seqno, IF5_MOBIPASS); -} // southbound IF4p5 fronthaul @@ -189,11 +187,12 @@ void fh_if5_south_in(RU_t *ru, recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->tti_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - + if (proc->first_rx == 0) { if (proc->tti_rx != *subframe) { - LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*subframe); - exit_fun("Exiting"); + LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d), resynching\n",proc->tti_rx,*subframe); + *frame=proc->frame_rx; + *subframe=proc->tti_rx; } if (proc->frame_rx != *frame) { @@ -324,48 +323,6 @@ void fh_slave_south_in(RU_t *ru, } -// asynchronous inbound if5 fronthaul from south (Mobipass) -void fh_if5_south_asynch_in_mobipass(RU_t *ru, - int *frame, - int *subframe) { - RU_proc_t *proc = &ru->proc; - LTE_DL_FRAME_PARMS *fp = ru->frame_parms; - recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_MOBIPASS); - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - int offset_mobipass = 40120; - pthread_mutex_lock(&proc->mutex_asynch_rxtx); - proc->tti_rx = ((proc->timestamp_rx-offset_mobipass)/fp->samples_per_tti)%10; - proc->frame_rx = ((proc->timestamp_rx-offset_mobipass)/(fp->samples_per_tti*10))&1023; - proc->tti_rx = (proc->timestamp_rx/fp->samples_per_tti)%10; - proc->frame_rx = (proc->timestamp_rx/(10*fp->samples_per_tti))&1023; - - if (proc->first_rx == 1) { - proc->first_rx =2; - *subframe = proc->tti_rx; - *frame = proc->frame_rx; - LOG_E(PHY,"[Mobipass]timestamp_rx:%llu, frame_rx %d, subframe: %d\n",(unsigned long long int)proc->timestamp_rx,proc->frame_rx,proc->tti_rx); - } else { - if (proc->tti_rx != *subframe) { - proc->first_rx++; - LOG_E(PHY,"[Mobipass]timestamp:%llu, tti_rx %d is not what we expect %d, first_rx:%d\n",(unsigned long long int)proc->timestamp_rx, proc->tti_rx,*subframe, proc->first_rx); - //exit_fun("Exiting"); - } - - if (proc->frame_rx != *frame) { - proc->first_rx++; - LOG_E(PHY,"[Mobipass]timestamp:%llu, frame_rx %d is not what we expect %d, first_rx:%d\n",(unsigned long long int)proc->timestamp_rx,proc->frame_rx,*frame, proc->first_rx); - // exit_fun("Exiting"); - } - - // temporary solution - *subframe = proc->tti_rx; - *frame = proc->frame_rx; - } - - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); -} // eNodeB_3GPP_BBU - - // asynchronous inbound if4p5 fronthaul from south void fh_if4p5_south_asynch_in(RU_t *ru, int *frame, @@ -456,7 +413,7 @@ void fh_if5_north_asynch_in(RU_t *ru, int tti_tx,frame_tx; openair0_timestamp timestamp_tx; recv_IF5(ru, ×tamp_tx, *subframe, IF5_RRH_GW_DL); - // printf("Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx); + // LOG_I(PHY,"Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx); tti_tx = (timestamp_tx/fp->samples_per_tti)%10; frame_tx = (timestamp_tx/(fp->samples_per_tti*10))&1023; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, proc->frame_tx ); @@ -696,7 +653,7 @@ void rx_rf(RU_t *ru, ru->ts_offset = proc->timestamp_rx; proc->timestamp_rx = 0; } else if (resynch==0 && (proc->timestamp_rx - old_ts != fp->samples_per_tti)) { - LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,ru->ts_offset); + LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,ru->ts_offset); ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); proc->timestamp_rx = ts-ru->ts_offset; } @@ -761,7 +718,7 @@ void rx_rf(RU_t *ru, *subframe = proc->tti_rx; } - //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); + //LOG_I(PHY,"timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); if (rxs != fp->samples_per_tti) { @@ -929,12 +886,8 @@ static void *ru_thread_asynch_rxtx( void *param ) { LOG_D(PHY,"ru_thread_asynch_rxtx: Waiting on incoming fronthaul\n"); - // asynchronous receive from south (Mobipass) - if (ru->fh_south_asynch_in) { - ru->fh_south_asynch_in(ru, &frame, &subframe); - } // asynchronous receive from north (RRU IF4/IF5) - else if (ru->fh_north_asynch_in) { + if (ru->fh_north_asynch_in) { if (subframe_select(ru->frame_parms,subframe)!=SF_UL) ru->fh_north_asynch_in(ru, &frame, &subframe); } else @@ -1185,21 +1138,22 @@ void wakeup_L1s(RU_t *ru) { L1_proc_t *proc = &eNB->proc; struct timespec t; LOG_D(PHY, "wakeup_L1s (num %d) for RU %d (%d.%d) ru->eNB_top:%p\n", ru->num_eNB, ru->idx, ru->proc.frame_rx, ru->proc.tti_rx, ru->eNB_top); - // call eNB function directly char string[20]; sprintf(string, "Incoming RU %d", ru->idx); + + // call eNB function directly VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.frame_rx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.tti_rx); AssertFatal(0==pthread_mutex_lock(&proc->mutex_RU),""); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOCK_MUTEX_RU+ru->idx, 1); - //printf("wakeup_L1s: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask[%d] %x\n", - // ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,ru->wait_cnt,ru->proc.subframe_rx,proc->RU_mask[ru->proc.subframe_rx]); + //LOG_I(PHY,"wakeup_L1s: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask[%d] %x\n", + // ru->proc.frame_rx,ru->proc.tti_rx,ru->idx,ru->wait_cnt,ru->proc.tti_rx,proc->RU_mask[ru->proc.tti_rx]); //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.frame_rx); - //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.subframe_rx); + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.tti_rx); clock_gettime(CLOCK_MONOTONIC, &ru->proc.t[ru->proc.tti_rx]); if (proc->RU_mask[ru->proc.tti_rx] == 0) { - //clock_gettime(CLOCK_MONOTONIC,&proc->t[ru->proc.subframe_rx]); + //clock_gettime(CLOCK_MONOTONIC,&proc->t[ru->proc.tti_rx]); proc->t[ru->proc.tti_rx] = ru->proc.t[ru->proc.tti_rx]; //start_meas(&proc->ru_arrival_time); LOG_D(PHY,"RU %d starting timer for frame %d subframe %d\n", ru->idx, ru->proc.frame_rx, ru->proc.tti_rx); @@ -1212,13 +1166,13 @@ void wakeup_L1s(RU_t *ru) { eNB->RU_list[i]->idx, eNB->RU_list[i]->proc.frame_rx, eNB->RU_list[i]->proc.tti_rx, ru_states[eNB->RU_list[i]->state]); if (ru == eNB->RU_list[i] && eNB->RU_list[i]->wait_cnt == 0) { - //AssertFatal((proc->RU_mask&(1<Mod_id,ru->proc.frame_rx,ru->proc.subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask); + //AssertFatal((proc->RU_mask&(1<Mod_id,ru->proc.frame_rx,ru->proc.tti_rx,ru->idx,eNB->num_RU,proc->RU_mask); proc->RU_mask[ru->proc.tti_rx] |= (1<RU_list[i]->state == RU_SYNC ||*/(eNB->RU_list[i]->is_slave==1 && eNB->RU_list[i]->wait_cnt>0 && ru!=eNB->RU_list[i] && ru->is_slave==0) ) { proc->RU_mask[ru->proc.tti_rx] |= (1<cnt %d, i->cnt %d\n",ru->idx,ru->proc.subframe_rx,proc->RU_mask[ru->proc.subframe_rx],i,ru->proc.frame_rx,ru->is_slave,ru->wait_cnt,eNB->RU_list[i]->wait_cnt); + //LOG_I(PHY,"RU %d, RU_mask[%d] %d, i %d, frame %d, slave %d, ru->cnt %d, i->cnt %d\n",ru->idx,ru->proc.tti_rx,proc->RU_mask[ru->proc.tti_rx],i,ru->proc.frame_rx,ru->is_slave,ru->wait_cnt,eNB->RU_list[i]->wait_cnt); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_RU, proc->RU_mask[ru->proc.tti_rx]); if (ru->is_slave == 0 && ( (proc->RU_mask[ru->proc.tti_rx]&(1<RU_list[i]->state == RU_RUN) { //This is master & the RRU has already been received @@ -1233,21 +1187,21 @@ void wakeup_L1s(RU_t *ru) { } //clock_gettime(CLOCK_MONOTONIC,&t); - //LOG_I(PHY,"RU mask is now %x, time is %lu\n",proc->RU_mask[ru->proc.subframe_rx], t.tv_nsec - proc->t[ru->proc.subframe_rx].tv_nsec); + //LOG_I(PHY,"RU mask is now %x, time is %lu\n",proc->RU_mask[ru->proc.tti_rx], t.tv_nsec - proc->t[ru->proc.tti_rx].tv_nsec); if (proc->RU_mask[ru->proc.tti_rx] == (1<num_RU)-1) { // all RUs have provided their information so continue on and wakeup eNB top LOG_D(PHY,"ru_mask is %d \n ", proc->RU_mask[ru->proc.tti_rx]); LOG_D(PHY,"the number of RU is %d, the current ru is RU %d \n ", (1<num_RU)-1, ru->idx); - LOG_D(PHY,"ru->proc.subframe_rx is %d \n", ru->proc.tti_rx); + LOG_D(PHY,"ru->proc.tti_rx is %d \n", ru->proc.tti_rx); LOG_D(PHY,"Resetting mask frame %d, subframe %d, this is RU %d\n", ru->proc.frame_rx, ru->proc.tti_rx, ru->idx); proc->RU_mask[ru->proc.tti_rx] = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_MASK_RU, proc->RU_mask[ru->proc.tti_rx]); clock_gettime(CLOCK_MONOTONIC,&t); //stop_meas(&proc->ru_arrival_time); - /*AssertFatal(t.tv_nsec < proc->t[ru->proc.subframe_rx].tv_nsec+5000000, "Time difference for subframe %d (Frame %d) => %lu > 5ms, this is RU %d\n", - ru->proc.subframe_rx, ru->proc.frame_rx, t.tv_nsec - proc->t[ru->proc.subframe_rx].tv_nsec, ru->idx);*/ + /*AssertFatal(t.tv_nsec < proc->t[ru->proc.tti_rx].tv_nsec+5000000, "Time difference for subframe %d (Frame %d) => %lu > 5ms, this is RU %d\n", + ru->proc.tti_rx, ru->proc.frame_rx, t.tv_nsec - proc->t[ru->proc.tti_rx].tv_nsec, ru->idx);*/ //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.frame_rx); - //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.subframe_rx); + //VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_L1S_RU+ru->idx, ru->proc.tti_rx); AssertFatal(0==pthread_mutex_unlock(&proc->mutex_RU),""); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_LOCK_MUTEX_RU+ru->idx, 0 ); // unlock RUs that are waiting for eNB processing to be completed @@ -1280,8 +1234,8 @@ void wakeup_L1s(RU_t *ru) { } // pthread_mutex_unlock(&proc->mutex_RU); - // LOG_D(PHY,"wakeup eNB top for for subframe %d\n", ru->proc.subframe_rx); - // ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.subframe_rx,string); + // LOG_D(PHY,"wakeup eNB top for for subframe %d\n", ru->proc.tti_rx); + // ru->eNB_top(eNB_list[0],ru->proc.frame_rx,ru->proc.tti_rx,string); ru->proc.emulate_rf_busy = 0; } @@ -1350,7 +1304,7 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { LTE_DL_FRAME_PARMS *fp = ru->frame_parms; openair0_config_t *cfg = &ru->openair0_cfg; - //printf("////////////////numerology in config = %d\n",numerology); + //LOG_I(PHY,"////////////////numerology in config = %d\n",numerology); int numerology = get_softmodem_params()->numerology; if(fp->N_RB_DL == 100) { @@ -1377,7 +1331,7 @@ void fill_rf_config(RU_t *ru, cfg->tx_bw = 40e6; cfg->rx_bw = 40e6; } else { - printf("Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology); + LOG_I(PHY,"Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology); cfg->sample_rate=30.72e6; cfg->samples_per_frame = 307200; cfg->tx_bw = 10e6; @@ -1416,7 +1370,7 @@ void fill_rf_config(RU_t *ru, cfg->tx_gain[i] = (double)ru->att_tx; cfg->rx_gain[i] = ru->max_rxgain-(double)ru->att_rx; cfg->configFilename = rf_config_file; - printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", + LOG_I(PHY,"channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", i, cfg->tx_gain[i], cfg->rx_gain[i], cfg->tx_freq[i], @@ -1437,9 +1391,9 @@ int setup_RU_buffers(RU_t *ru) { if (ru) { frame_parms = ru->frame_parms; - printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); + LOG_I(PHY,"setup_RU_buffers: frame_parms = %p\n",frame_parms); } else { - printf("RU not initialized (NULL pointer)\n"); + LOG_I(PHY,"RU not initialized (NULL pointer)\n"); return(-1); } @@ -1462,7 +1416,7 @@ int setup_RU_buffers(RU_t *ru) { ru->sf_extension /= 4; ru->end_of_burst_delay /= 4; } else { - printf("not handled, todo\n"); + LOG_I(PHY,"not handled, todo\n"); exit(1); } } else { @@ -1476,13 +1430,13 @@ int setup_RU_buffers(RU_t *ru) { for (i=0; inb_rx; i++) { card = i/4; ant = i%4; - printf("Mapping RU id %d, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + LOG_I(PHY,"Mapping RU id %d, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); free(ru->common.rxdata[i]); ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain+ant]; - printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); + LOG_I(PHY,"rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); for (j=0; j<16; j++) { - printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); + LOG_I(PHY,"rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); ru->common.rxdata[i][j] = 16-j; } } @@ -1490,13 +1444,13 @@ int setup_RU_buffers(RU_t *ru) { for (i=0; inb_tx; i++) { card = i/4; ant = i%4; - printf("Mapping RU id %d, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + LOG_I(PHY,"Mapping RU id %d, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); free(ru->common.txdata[i]); ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain+ant]; - printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]); + LOG_I(PHY,"txdata[%d] @ %p\n",i,ru->common.txdata[i]); for (j=0; j<16; j++) { - printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]); + LOG_I(PHY,"txbuffer %d: %x\n",j,ru->common.txdata[i][j]); ru->common.txdata[i][j] = 16-j; } } @@ -1623,7 +1577,7 @@ static void *ru_thread_tx( void *param ) { } if (eNB_proc->RU_mask_tx != (1<num_RU)-1) { // not all RUs have provided their information so return - //printf("Not all RUs have provided their info (mask = %d), RU %d, num_RUs %d\n", eNB_proc->RU_mask_tx,ru->idx,eNB->num_RU); + //LOG_I(PHY,"Not all RUs have provided their info (mask = %d), RU %d, num_RUs %d\n", eNB_proc->RU_mask_tx,ru->idx,eNB->num_RU); AssertFatal((ret=pthread_mutex_unlock(&eNB_proc->mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); } else { // all RUs TX are finished so send the ready signal to eNB processing eNB_proc->RU_mask_tx = 0; @@ -1644,7 +1598,7 @@ static void *ru_thread_tx( void *param ) { } } - //printf("ru_thread_tx: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask_tx %d\n", + //LOG_I(PHY,"ru_thread_tx: Frame %d, Subframe %d: RU %d done (wait_cnt %d),RU_mask_tx %d\n", //eNB_proc->frame_rx,eNB_proc->subframe_rx,ru->idx,ru->wait_cnt,eNB_proc->RU_mask_tx); } @@ -1676,12 +1630,10 @@ static void *ru_thread( void *param ) { LOG_I(PHY,"Starting RU %d (%s,%s),\n", ru->idx, NB_functions[ru->function], NB_timing[ru->if_timing]); if(get_softmodem_params()->emulate_rf) { - fill_rf_config(ru,ru->rf_config_file); - init_frame_parms(ru->frame_parms,1); phy_init_RU(ru); if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); + LOG_I(PHY,"Exiting, cannot initialize RU Buffers\n"); exit(-1); } @@ -1693,24 +1645,20 @@ static void *ru_thread( void *param ) { ru->state = RU_RUN; } else if (ru->has_ctrl_prt == 0) { // There is no control port: start everything here - LOG_I(PHY, "RU %d has not ctrl port\n",ru->idx); + LOG_I(PHY, "RU %d has no OAI ctrl port\n",ru->idx); - if (ru->if_south == LOCAL_RF) { - fill_rf_config(ru,ru->rf_config_file); - init_frame_parms(ru->frame_parms,1); - ru->frame_parms->nb_antennas_rx = ru->nb_rx; - phy_init_RU(ru); - openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + ru->frame_parms->nb_antennas_rx = ru->nb_rx; - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } + if (ru->if_south == LOCAL_RF) openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret); + phy_init_RU(ru); + + + if (setup_RU_buffers(ru)!=0) { + LOG_I(PHY,"Exiting, cannot initialize RU Buffers\n"); + exit(-1); } AssertFatal((ret=pthread_mutex_lock(&RC.ru_mutex))==0,"mutex_lock returns %d\n",ret); @@ -1745,9 +1693,9 @@ static void *ru_thread( void *param ) { // Start RF device if any if (ru->start_rf) { - if (ru->start_rf(ru) != 0) - LOG_E(HW,"Could not start the RF device\n"); - else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + if (ru->start_rf(ru) != 0) + AssertFatal(1==0,"Could not start the RF device\n"); + else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_D(PHY,"RU %d no rf device\n",ru->idx); } @@ -1781,7 +1729,6 @@ static void *ru_thread( void *param ) { // synchronization on input FH interface, acquire signals/data and block if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&subframe); else AssertFatal(1==0, "No fronthaul interface at south port"); - #ifdef PHY_TX_THREAD if(first_phy_tx == 0) { @@ -1945,7 +1892,7 @@ static void *ru_thread( void *param ) { } // ru->state = RU_RUN } // while !oai_exit - printf( "Exiting ru_thread \n"); + LOG_I(PHY, "Exiting ru_thread \n"); if (!(get_softmodem_params()->emulate_rf)) { if (ru->stop_rf != NULL) { @@ -2017,6 +1964,7 @@ void *ru_thread_synch(void *arg) { #if defined(PRE_SCD_THREAD) void *pre_scd_thread( void *param ) { + void rlc_tick(int, int); static int eNB_pre_scd_status; protocol_ctxt_t ctxt; int frame; @@ -2051,6 +1999,7 @@ void *pre_scd_thread( void *param ) { AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"mutex_unlock returns %d\n",ret); PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, Mod_id, ENB_FLAG_YES, NOT_A_RNTI, frame, subframe,Mod_id); + rlc_tick(frame, subframe); pdcp_run(&ctxt); for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { @@ -2188,6 +2137,12 @@ static void *rf_tx( void *param ) { #endif + +int start_streaming(RU_t *ru) { + LOG_I(PHY,"Starting streaming on third-party RRU\n"); + return(ru->ifdevice.thirdparty_startstreaming(&ru->ifdevice)); +} + int start_if(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB) { return(ru->ifdevice.trx_start_func(&ru->ifdevice)); } @@ -2233,7 +2188,7 @@ void reset_proc(RU_t *ru) { void init_RU_proc(RU_t *ru) { - int i=0, ret; + int i=0; RU_proc_t *proc; pthread_attr_t *attr_FH=NULL, *attr_FH1=NULL, *attr_prach=NULL, *attr_asynch=NULL, *attr_synch=NULL, *attr_emulateRF=NULL, *attr_ctrl=NULL, *attr_prach_br=NULL; //pthread_attr_t *attr_fep=NULL; @@ -2302,7 +2257,17 @@ void init_RU_proc(RU_t *ru) { attr_prach_br = &proc->attr_prach_br; #endif - if (ru->function!=eNodeB_3GPP) pthread_create( &proc->pthread_ctrl, attr_ctrl, ru_thread_control, (void *)ru ); + if (ru->has_ctrl_prt == 1) pthread_create( &proc->pthread_ctrl, attr_ctrl, ru_thread_control, (void*)ru ); + else { + if (ru->start_if) { + LOG_I(PHY,"Starting IF interface for RU %d\n",ru->idx); + AssertFatal( + ru->start_if(ru,NULL) == 0, "Could not start the IF device\n"); + + if (ru->if_south != LOCAL_RF) wait_eNBs(); + } + } + pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void *)ru ); #if defined(PRE_SCD_THREAD) @@ -2341,23 +2306,6 @@ void init_RU_proc(RU_t *ru) { LOG_I(PHY,"%s() DJP - added creation of pthread_prach\n", __FUNCTION__); pthread_create( &proc->pthread_prach, attr_prach, ru_thread_prach, (void *)ru ); ru->state=RU_RUN; - if(!get_softmodem_params()->emulate_rf) - { - fill_rf_config(ru,ru->rf_config_file); - init_frame_parms(ru->frame_parms,1); - ru->frame_parms->nb_antennas_rx = ru->nb_rx; - phy_init_RU(ru); - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - if (ret < 0) { - LOG_I(PHY,"Exiting, cannot load device. Make sure that your SDR board is connected!\n"); - exit(1); - } - - if (setup_RU_buffers(ru)!=0) { - LOG_I(PHY,"Exiting, cannot initialize RU Buffers\n"); - exit(1); - } - } } if (get_thread_worker_conf() == WORKER_ENABLE) { @@ -2366,7 +2314,7 @@ void init_RU_proc(RU_t *ru) { } if (opp_enabled == 1) pthread_create(&ru->ru_stats_thread,NULL,ru_stats_thread,(void *)ru); - +/* if (ru->function == eNodeB_3GPP) { usleep(10000); LOG_I(PHY, "Signaling main thread that RU %d (is_slave %d,send_dmrs %d) is ready in state %s\n",ru->idx,ru->is_slave,ru->generate_dmrs_sync,ru_states[ru->state]); @@ -2375,6 +2323,7 @@ void init_RU_proc(RU_t *ru) { pthread_cond_signal(&RC.ru_cond); AssertFatal((ret=pthread_mutex_unlock(&RC.ru_mutex))==0,"mutex_unlock returns %d\n",ret); } + */ } @@ -2537,6 +2486,7 @@ void init_precoding_weights(PHY_VARS_eNB *eNB) { void set_function_spec_param(RU_t *ru) { int ret; + switch (ru->if_south) { case LOCAL_RF: // this is an RU with integrated RF (RRU, eNB) if (ru->function == NGFI_RRU_IF5) { // IF5 RRU @@ -2557,10 +2507,10 @@ void set_function_spec_param(RU_t *ru) { reset_meas(&ru->compression); reset_meas(&ru->transport); ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); + LOG_I(PHY,"NGFI_RRU_IF5: openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); + LOG_I(PHY,"Exiting, cannot initialize transport protocol\n"); exit(-1); } } else if (ru->function == NGFI_RRU_IF4p5) { @@ -2581,10 +2531,10 @@ void set_function_spec_param(RU_t *ru) { reset_meas(&ru->compression); reset_meas(&ru->transport); ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); + LOG_I(PHY,"NGFI_RRU_if4p5 : openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); + LOG_I(PHY,"Exiting, cannot initialize transport protocol\n"); exit(-1); } @@ -2604,7 +2554,7 @@ void set_function_spec_param(RU_t *ru) { ru->fh_south_out = tx_rf; // local synchronous RF TX ru->start_rf = start_rf; // need to start the local RF interface ru->stop_rf = stop_rf; - printf("configuring ru_id %d (start_rf %p)\n", ru->idx, start_rf); + LOG_I(PHY,"NFGI_RRU_IF4p5: configuring ru_id %d (start_rf %p)\n", ru->idx, start_rf); /* if (ru->function == eNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise fill_rf_config(ru,rf_config_file); @@ -2614,7 +2564,7 @@ void set_function_spec_param(RU_t *ru) { ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); + LOG_I(PHY,"Exiting, cannot initialize RU Buffers\n"); exit(-1); }*/ break; @@ -2627,25 +2577,22 @@ void set_function_spec_param(RU_t *ru) { if (ru->if_timing == synch_to_other) { ru->fh_south_in = fh_slave_south_in; // synchronize to master - ru->fh_south_out = fh_if5_mobipass_south_out; // use send_IF5 for mobipass - ru->fh_south_asynch_in = fh_if5_south_asynch_in_mobipass; // UL is asynchronous } else { ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception ru->fh_south_out = fh_if5_south_out; // synchronous IF5 transmission ru->fh_south_asynch_in = NULL; // no asynchronous UL } - - ru->start_rf = NULL; // no local RF + ru->start_rf = ru->eth_params.transp_preference == ETH_UDP_IF5_ECPRI_MODE ? start_streaming : NULL; ru->stop_rf = NULL; ru->start_if = start_if; // need to start if interface for IF5 ru->ifdevice.host_type = RAU_HOST; ru->ifdevice.eth_params = &ru->eth_params; ru->ifdevice.configure_rru = configure_ru; ret = openair0_transport_load(&ru->ifdevice,&ru->openair0_cfg,&ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); + LOG_I(PHY,"REMOTE_IF5: openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); + LOG_I(PHY,"Exiting, cannot initialize transport protocol\n"); exit(-1); } @@ -2668,10 +2615,10 @@ void set_function_spec_param(RU_t *ru) { ru->ifdevice.eth_params = &ru->eth_params; ru->ifdevice.configure_rru = configure_ru; ret = openair0_transport_load(&ru->ifdevice, &ru->openair0_cfg, &ru->eth_params); - printf("openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); + LOG_I(PHY,"REMOTE IF4p5: openair0_transport_init returns %d for ru_id %d\n", ret, ru->idx); if (ret<0) { - printf("Exiting, cannot initialize transport protocol\n"); + LOG_I(PHY,"Exiting, cannot initialize transport protocol\n"); exit(-1); } @@ -2685,12 +2632,14 @@ void set_function_spec_param(RU_t *ru) { } malloc_IF4p5_buffer(ru); + break; default: LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); break; } // switch on interface type + } //extern void RCconfig_RU(void); @@ -2780,6 +2729,11 @@ void init_RU(char *rf_config_file, int send_dmrssync) { LOG_I(PHY, "Initializing RRU descriptor %d : (%s,%s,%d)\n", ru_id, ru_if_types[ru->if_south], NB_timing[ru->if_timing], ru->function); set_function_spec_param(ru); + if (ru->function != NGFI_RRU_IF4p5 && ru->function != NGFI_RRU_IF5) { + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + } + LOG_I(PHY, "Starting ru_thread %d, is_slave %d, send_dmrs %d\n", ru_id, ru->is_slave, ru->generate_dmrs_sync); init_RU_proc(ru); } // for ru_id @@ -2793,7 +2747,7 @@ void stop_ru(RU_t *ru) { #if defined(PRE_SCD_THREAD) || defined(PHY_TX_THREAD) int *status; #endif - printf("Stopping RU %p processing threads\n",(void *)ru); + LOG_I(PHY,"Stopping RU %p processing threads\n",(void *)ru); #if defined(PRE_SCD_THREAD) if(ru) { @@ -2847,7 +2801,7 @@ void init_ru_vnf(void) { pthread_mutex_init(&RC.ru_mutex,NULL); pthread_cond_init(&RC.ru_cond,NULL); // read in configuration file) - printf("configuring RU from file\n"); + LOG_I(PHY,"configuring RU from file\n"); RCconfig_RU(); LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_L1_inst,RC.nb_RU,get_nprocs()); @@ -2937,7 +2891,7 @@ void RCconfig_RU(void) { RC.ru[j] = (RU_t *)malloc(sizeof(RU_t)); memset((void *)RC.ru[j],0,sizeof(RU_t)); RC.ru[j]->idx = j; - printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]); + LOG_I(PHY,"Creating RC.ru[%d]:%p\n", j, RC.ru[j]); RC.ru[j]->if_timing = synch_to_ext_device; if (RC.nb_L1_inst >0) @@ -2947,7 +2901,7 @@ void RCconfig_RU(void) { for (i=0; inum_eNB; i++) RC.ru[j]->eNB_list[i] = RC.eNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0]; - RC.ru[j]->has_ctrl_prt = 1; + RC.ru[j]->has_ctrl_prt = 0; if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); @@ -2994,7 +2948,7 @@ void RCconfig_RU(void) { RC.ru[j]->if_south = LOCAL_RF; RC.ru[j]->function = eNodeB_3GPP; RC.ru[j]->state = RU_RUN; - printf("Setting function for RU %d to eNodeB_3GPP\n",j); + LOG_I(PHY,"Setting function for RU %d to eNodeB_3GPP\n",j); } else { RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); @@ -3004,42 +2958,43 @@ void RCconfig_RU(void) { // Check if control port set if (!(config_isparamset(RUParamList.paramarray[j],RU_REMOTE_PORTC_IDX)) ) { - printf("Removing control port for RU %d\n",j); + LOG_I(PHY,"Removing control port for RU %d\n",j); RC.ru[j]->has_ctrl_prt = 0; } else { RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); - printf(" Control port %u \n",RC.ru[j]->eth_params.my_portc); + LOG_I(PHY," Control port %u \n",RC.ru[j]->eth_params.my_portc); } if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { RC.ru[j]->if_south = LOCAL_RF; RC.ru[j]->function = NGFI_RRU_IF5; RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j); + LOG_I(PHY,"Setting function for RU %d to NGFI_RRU_IF5 (udp)\n",j); } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { RC.ru[j]->if_south = LOCAL_RF; RC.ru[j]->function = NGFI_RRU_IF5; RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j); + LOG_I(PHY,"Setting function for RU %d to NGFI_RRU_IF5 (raw)\n",j); } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { RC.ru[j]->if_south = LOCAL_RF; RC.ru[j]->function = NGFI_RRU_IF4p5; RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j); + RC.ru[j]->has_ctrl_prt =1; + LOG_I(PHY,"Setting function for RU %d to NGFI_RRU_IF4p5 (udp)\n",j); } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { RC.ru[j]->if_south = LOCAL_RF; RC.ru[j]->function = NGFI_RRU_IF4p5; RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; - printf("Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j); + LOG_I(PHY,"Setting function for RU %d to NGFI_RRU_IF4p5 (raw)\n",j); } - printf("RU %d is_slave=%s\n",j,*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr)); + LOG_I(PHY,"RU %d is_slave=%s\n",j,*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr)); if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) RC.ru[j]->is_slave=1; else RC.ru[j]->is_slave=0; - printf("RU %d ota_sync_enabled=%s\n",j,*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr)); + LOG_I(PHY,"RU %d ota_sync_enabled=%s\n",j,*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr)); if (strcmp(*(RUParamList.paramarray[j][RU_OTA_SYNC_ENABLE_IDX].strptr), "yes") == 0) RC.ru[j]->ota_sync_enable=1; else RC.ru[j]->ota_sync_enable=0; @@ -3053,8 +3008,8 @@ void RCconfig_RU(void) { for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; } //strcmp(local_rf, "yes") == 0 - else { - printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); +else { + LOG_I(PHY,"RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); @@ -3062,34 +3017,34 @@ void RCconfig_RU(void) { RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); - + if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; + RC.ru[j]->if_south = REMOTE_IF5; + RC.ru[j]->function = NGFI_RAU_IF5; + RC.ru[j]->eth_params.transp_preference = ETH_UDP_MODE; + } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_ecpri_if5") == 0) { + RC.ru[j]->if_south = REMOTE_IF5; + RC.ru[j]->function = NGFI_RAU_IF5; + RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF5_ECPRI_MODE; } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; + RC.ru[j]->if_south = REMOTE_IF5; + RC.ru[j]->function = NGFI_RAU_IF5; + RC.ru[j]->eth_params.transp_preference = ETH_RAW_MODE; } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "udp_if4p5") == 0) { - RC.ru[j]->if_south = REMOTE_IF4p5; - RC.ru[j]->function = NGFI_RAU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + RC.ru[j]->if_south = REMOTE_IF4p5; + RC.ru[j]->function = NGFI_RAU_IF4p5; + RC.ru[j]->eth_params.transp_preference = ETH_UDP_IF4p5_MODE; + RC.ru[j]->has_ctrl_prt = 1; } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if4p5") == 0) { - RC.ru[j]->if_south = REMOTE_IF4p5; - RC.ru[j]->function = NGFI_RAU_IF4p5; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; - } else if (strcmp(*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr), "raw_if5_mobipass") == 0) { - RC.ru[j]->if_south = REMOTE_IF5; - RC.ru[j]->function = NGFI_RAU_IF5; - RC.ru[j]->if_timing = synch_to_other; - RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF5_MOBIPASS; + RC.ru[j]->if_south = REMOTE_IF4p5; + RC.ru[j]->function = NGFI_RAU_IF4p5; + RC.ru[j]->eth_params.transp_preference = ETH_RAW_IF4p5_MODE; + + if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) RC.ru[j]->is_slave=1; + else RC.ru[j]->is_slave=0; } - - if (strcmp(*(RUParamList.paramarray[j][RU_IS_SLAVE_IDX].strptr), "yes") == 0) RC.ru[j]->is_slave=1; - else RC.ru[j]->is_slave=0; } /* strcmp(local_rf, "yes") != 0 */ - + RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); diff --git a/targets/RT/USER/rcc_if5.gtkw b/targets/RT/USER/rcc_if5.gtkw index d64a9ca0fb..34c6bab5d1 100644 --- a/targets/RT/USER/rcc_if5.gtkw +++ b/targets/RT/USER/rcc_if5.gtkw @@ -1,41 +1,67 @@ [*] -[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Sun Jul 31 13:30:42 2016 +[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI +[*] Tue Sep 24 06:59:08 2019 [*] [dumpfile] "/tmp/openair_dump_eNB.vcd" -[dumpfile_mtime] "Sun Jul 31 13:21:59 2016" -[dumpfile_size] 18273240 -[savefile] "/home/fourmi/openairinterface5g/targets/RT/USER/rcc_if5.gtkw" -[timestart] 24070893000 -[size] 1301 716 -[pos] 309 0 -*-19.793451 29026062100 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -[sst_width] 284 -[signals_width] 262 +[dumpfile_mtime] "Mon Sep 23 20:04:56 2019" +[dumpfile_size] 1625759 +[savefile] "/home/orange/aw2s/openairinterface5g/targets/RT/USER/rcc_if5.gtkw" +[timestart] 12600104000 +[size] 1215 1000 +[pos] 0 22 +*-19.506693 12600920638 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[sst_width] 386 +[signals_width] 344 [sst_expanded] 1 -[sst_vpaned_height] 294 +[sst_vpaned_height] 303 +@29 +functions.send_if5 +@28 +functions.recv_if5 @24 variables.trx_ts[63:0] variables.trx_tst[63:0] @28 -functions.send_if5 -functions.recv_if5 functions.eNB_thread_rxtx0 @24 +variables.frame_number_RX0_RU[63:0] +variables.subframe_number_RX0_RU[63:0] +variables.frame_number_TX0_RU[63:0] +variables.subframe_number_TX0_RU[63:0] +@28 +functions.mac_schedule_dlsch +functions.macxface_eNB_dlsch_ulsch_scheduler +functions.macxface_ue_scheduler +functions.phy_eNB_ofdm_mod_l +@24 variables.frame_number_RX0_eNB[63:0] variables.subframe_number_RX0_eNB[63:0] variables.frame_number_TX0_eNB[63:0] variables.subframe_number_TX0_eNB[63:0] -@28 -functions.eNB_thread_rxtx1 -@24 variables.frame_number_RX1_eNB[63:0] variables.subframe_number_RX1_eNB[63:0] variables.frame_number_TX1_eNB[63:0] variables.subframe_number_TX1_eNB[63:0] @28 +functions.phy_eNB_dlsch_modulation +functions.phy_eNB_dlsch_encoding +functions.phy_eNB_dlsch_scrambling +functions.phy_eNB_beam_precoding +functions.phy_enb_pdcch_tx +functions.phy_enb_prach_rx +functions.phy_procedures_ru_feprx0 +functions.phy_procedures_eNb_rx_uespec0 +functions.phy_procedures_eNb_rx_uespec1 +functions.phy_enb_sfgen +functions.phy_procedures_eNb_tx0 +functions.phy_procedures_eNb_tx1 +functions.phy_procedures_ru_feprx1 +functions.phy_procedures_ru_feptx_ofdm0 +functions.phy_procedures_ru_feptx_ofdm1 +functions.phy_procedures_ru_feptx_prec0 +functions.phy_procedures_ru_feptx_prec1 +functions.eNB_thread_rxtx1 functions.phy_enb_sfgen -functions.phy_eNB_slot_fep functions.phy_enb_prach_rx @24 variables.dci_info[63:0] diff --git a/targets/RT/USER/ru_control.c b/targets/RT/USER/ru_control.c index 6daf0f4dfa..7ac6a8913e 100644 --- a/targets/RT/USER/ru_control.c +++ b/targets/RT/USER/ru_control.c @@ -524,7 +524,7 @@ void* ru_thread_control( void* param ) } - ru->state = (ru->function==eNodeB_3GPP)? RU_RUN : RU_IDLE; + ru->state = (ru->function==eNodeB_3GPP || ru->if_south == REMOTE_IF5)? RU_RUN : RU_IDLE; LOG_I(PHY,"Control channel ON for RU %d\n", ru->idx); while (!oai_exit) // Change the cond