diff --git a/NOTICE.md b/NOTICE.md index 65c6105660..96b5d4c552 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -4,7 +4,7 @@ For more details of the license, refer to [LICENSE](LICENSE) file in the same di However, the source code also contains third party software that is acknowledged here for reference. -## Credits for LFDS user space source code located in folder openair2/UTILS/LFDS/liblfds6.1.1/ ## +## Credits for LFDS user space source code located in folder openair2/UTILS/LFDS/ ## See on [liblfds website](https://liblfds.org/) the license section. diff --git a/ci-scripts/.gitignore b/ci-scripts/.gitignore index d77a672c0c..dc5e7c7476 100644 --- a/ci-scripts/.gitignore +++ b/ci-scripts/.gitignore @@ -5,3 +5,5 @@ iperf_*.* phones_list.txt modules_list.txt test_results*.html +pMain* +__pycache__ diff --git a/ci-scripts/Jenkinsfile-inria-r2lab b/ci-scripts/Jenkinsfile-inria-r2lab index 3c4dddae8b..ca6893dc4f 100644 --- a/ci-scripts/Jenkinsfile-inria-r2lab +++ b/ci-scripts/Jenkinsfile-inria-r2lab @@ -142,13 +142,39 @@ pipeline { stage ("Load Images") { steps { script { + // Adding a tempo after booking leases + sh "sleep 10" + sh "ssh -t inria_oaici@faraday.inria.fr 'rleases --check'" + sh "ssh -t inria_oaici@faraday.inria.fr 'all-off'" + sh "sleep 10" + echo '\u2705 \u001B[32mLoad Image for Python Executor\u001B[0m' - sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labPythonExeIdx} > /dev/null 2>&1'" - sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labPythonExeIdx}'" + try { + //sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labPythonExeIdx} > /dev/null 2>&1'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labPythonExeIdx}'" + } catch (Exception e) { + echo "Why is it wrong?" + } + try { + //sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labPythonExeIdx}'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rwait ${r2labPythonExeIdx}'" + } catch (Exception e) { + echo "Why is it wrong?" + } echo '\u2705 \u001B[32mLoad Image for two (2) eNBs\u001B[0m' - sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labENB0Idx},${r2labENB1Idx} > /dev/null 2>&1'" - sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labENB0Idx},${r2labENB1Idx}'" + try { + //sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labENB0Idx},${r2labENB1Idx} > /dev/null 2>&1'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labENB0Idx},${r2labENB1Idx}" + } catch (Exception e) { + echo "Why is it wrong?" + } + try { + //sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labENB0Idx},${r2labENB1Idx}'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rwait ${r2labENB0Idx},${r2labENB1Idx}'" + } catch (Exception e) { + echo "Why is it wrong?" + } sh "ssh -t inria_oaici@faraday.inria.fr 'uon ${r2labENB0Idx},${r2labENB1Idx}'" sh "sleep 5" sh "ssh -t inria_oaici@faraday.inria.fr 'uon ${r2labENB0Idx},${r2labENB1Idx}'" diff --git a/ci-scripts/checkCodingFormattingRules.sh b/ci-scripts/checkCodingFormattingRules.sh index 6ac43ca19f..fb159d4da0 100755 --- a/ci-scripts/checkCodingFormattingRules.sh +++ b/ci-scripts/checkCodingFormattingRules.sh @@ -62,6 +62,30 @@ then NB_FILES_TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt --recursive *.c *.h | grep -c Formatted ` echo "Nb Files that do NOT follow OAI rules: $NB_FILES_TO_FORMAT" echo $NB_FILES_TO_FORMAT > ./oai_rules_result.txt + + # Testing Circular Dependencies protection + awk '/#[ \t]*ifndef/ { gsub("^.*ifndef *",""); if (names[$1]!="") print "files with same {define ", FILENAME, names[$1]; names[$1]=FILENAME } /#[ \t]*define/ { gsub("^.*define *",""); if(names[$1]!=FILENAME) print "error in declaration", FILENAME, $1, names[$1]; nextfile }' `find openair* common targets executables -name *.h |grep -v LFDS` > header-files-w-incorrect-define.txt + + # Testing if explicit GNU GPL license banner + egrep -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "General Public License" . > files-w-gnu-gpl-license-banner.txt + + # Looking at exotic/suspect banner + LIST_OF_FILES_W_BANNER=`egrep -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "Copyright|copyleft" .` + if [ -f ./files-w-suspect-banner.txt ]; then rm -f ./files-w-suspect-banner.txt; fi + for FILE in $LIST_OF_FILES_W_BANNER + do + IS_NFAPI=`echo $FILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext"` + IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FILE` + IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence" $FILE` + IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h"` + if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] + then + if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ] + then + echo $FILE >> ./files-w-suspect-banner.txt + fi + fi + done exit 0 fi @@ -131,8 +155,25 @@ if [ -f oai_rules_result_list.txt ] then rm -f oai_rules_result_list.txt fi +if [ -f header-files-w-incorrect-define.txt ] +then + rm -f header-files-w-incorrect-define.txt +fi +if [ -f files-w-gnu-gpl-license-banner.txt ] +then + rm -f files-w-gnu-gpl-license-banner.txt +fi +if [ -f files-w-suspect-banner.txt ] +then + rm -f files-w-suspect-banner.txt +fi +awk '/#[ \t]*ifndef/ { gsub("^.*ifndef *",""); if (names[$1]!="") print "files with same {define ", FILENAME, names[$1]; names[$1]=FILENAME } /#[ \t]*define/ { gsub("^.*define *",""); if(names[$1]!=FILENAME) print "error in declaration", FILENAME, $1, names[$1]; nextfile }' `find openair* common targets executables -name *.h |grep -v LFDS` > header-files-w-incorrect-define-tmp.txt + for FULLFILE in $MODIFIED_FILES do + # sometimes, we remove files + if [ ! -f $FULLFILE ]; then continue; fi + filename=$(basename -- "$FULLFILE") EXT="${filename##*.}" if [ $EXT = "c" ] || [ $EXT = "h" ] || [ $EXT = "cpp" ] || [ $EXT = "hpp" ] @@ -144,8 +185,32 @@ do echo $FULLFILE echo $FULLFILE >> ./oai_rules_result_list.txt fi + # Testing if explicit GNU GPL license banner + egrep -i "General Public License" $FULLFILE >> files-w-gnu-gpl-license-banner.txt + # Looking at exotic/suspect banner + IS_BANNER=`egrep -i -c "Copyright|copyleft" $FULLFILE` + if [ $IS_BANNER -ne 0 ] + then + IS_NFAPI=`echo $FULLFILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext"` + IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FULLFILE` + IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence" $FULLFILE` + IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h"` + if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] + then + if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ] + then + echo $FILE >> ./files-w-suspect-banner.txt + fi + fi + fi + fi + # Testing Circular Dependencies protection + if [ $EXT = "h" ] || [ $EXT = "hpp" ] + then + grep $FULLFILE header-files-w-incorrect-define-tmp.txt >> header-files-w-incorrect-define.txt fi done +rm -f header-files-w-incorrect-define-tmp.txt echo "" echo " ----------------------------------------------------------" echo "Nb Files that do NOT follow OAI rules: $NB_TO_FORMAT" 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 fbb8c5d6f8..de58950df4 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 @@ -288,7 +288,7 @@ MCEs = ( mnc_length = 2; } service_id=0; - lcid=8; #this must be properly defined lcid:8+service:0 -> rab_id:8 + lcid=5; #this must be properly defined lcid:8+service:0 -> rab_id:5 } ); } diff --git a/ci-scripts/constants.py b/ci-scripts/constants.py new file mode 100644 index 0000000000..1e7e84fb32 --- /dev/null +++ b/ci-scripts/constants.py @@ -0,0 +1,71 @@ +#/* +# * 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 +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Version +#----------------------------------------------------------- +Version = '0.2' + +#----------------------------------------------------------- +# Constants +#----------------------------------------------------------- +ALL_PROCESSES_OK = 0 +ENB_PROCESS_FAILED = -1 +ENB_PROCESS_OK = +1 +ENB_PROCESS_SEG_FAULT = -11 +ENB_PROCESS_ASSERTION = -12 +ENB_PROCESS_REALTIME_ISSUE = -13 +ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 +ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 +HSS_PROCESS_FAILED = -2 +HSS_PROCESS_OK = +2 +MME_PROCESS_FAILED = -3 +MME_PROCESS_OK = +3 +SPGW_PROCESS_FAILED = -4 +SPGW_PROCESS_OK = +4 +UE_IP_ADDRESS_ISSUE = -5 +OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 +OAI_UE_PROCESS_COULD_NOT_SYNC = -21 +OAI_UE_PROCESS_ASSERTION = -22 +OAI_UE_PROCESS_FAILED = -23 +OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 +OAI_UE_PROCESS_SEG_FAULT = -25 +OAI_UE_PROCESS_OK = +6 + +UE_STATUS_DETACHED = 0 +UE_STATUS_DETACHING = 1 +UE_STATUS_ATTACHING = 2 +UE_STATUS_ATTACHED = 3 + +X2_HO_REQ_STATE__IDLE = 0 +X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 +X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 +X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 +X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 diff --git a/ci-scripts/cppcheck_suppressions.list b/ci-scripts/cppcheck_suppressions.list index 4536f57315..cad2aab88b 100644 --- a/ci-scripts/cppcheck_suppressions.list +++ b/ci-scripts/cppcheck_suppressions.list @@ -76,6 +76,11 @@ nullPointer:common/utils/T/local_tracer.c:243 // first iteration of the loop nullPointer:common/utils/T/tracer/multi.c:264 nullPointer:common/utils/T/tracer/multi.c:265 +//----------------------------------------------------------------------------- +// this file is used for testing the RLC V2 implementation, this error is +// not a problem, the programmer has to know what she does when writing +// the tests +arrayIndexOutOfBounds:openair2/LAYER2/rlc_v2/tests/test.c:401 // //***************************************************************************** // diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py new file mode 100644 index 0000000000..3a52a6118c --- /dev/null +++ b/ci-scripts/epc.py @@ -0,0 +1,400 @@ +#/* +# * 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 +import signal + +from multiprocessing import Process, Lock, SimpleQueue + +#----------------------------------------------------------- +# OAI Testing modules +#----------------------------------------------------------- +import sshconnection as SSH +import helpreadme as HELP +import constants as CONST +import html + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class EPCManagement(): + + def __init__(self): + + self.IPAddress = '' + self.UserName = '' + self.Password = '' + self.SourceCodePath = '' + self.Type = '' + self.PcapFileName = '' + self.htmlObj = None + self.testCase_id = '' + +#----------------------------------------------------------- +# Setter and Getters on Public Members +#----------------------------------------------------------- + + def SetIPAddress(self, ipaddress): + self.IPAddress = ipaddress + def GetIPAddress(self): + return self.IPAddress + def SetUserName(self, username): + self.UserName = username + def GetUserName(self): + return self.UserName + def SetPassword(self, password): + self.Password = password + def GetPassword(self): + return self.Password + def SetSourceCodePath(self, sourcecodepath): + self.SourceCodePath = sourcecodepath + def GetSourceCodePath(self): + return self.SourceCodePath + def SetType(self, kind): + self.Type = kind + def GetType(self): + return self.Type + def SetHtmlObj(self, obj): + self.htmlObj = obj + def SetTestCase_id(self, idx): + self.testCase_id = idx + +#----------------------------------------------------------- +# EPC management functions +#----------------------------------------------------------- + + def InitializeHSS(self): + 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) + if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') + self.PcapFileName = 'epc_' + self.testCase_id + '.pcap' + mySSH.command('echo ' + self.Password + ' | sudo -S rm -f ' + self.PcapFileName, '\$', 5) + mySSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.SourceCodePath + '/scripts/' + self.PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.UserName, 5) + mySSH.command('echo ' + self.Password + ' | sudo -S mkdir -p logs', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) + mySSH.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) + mySSH.command('chmod 755 ./my-hss.sh', '\$', 5) + mySSH.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.SourceCodePath + '/scripts -o ' + self.SourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) + elif re.match('OAI', self.Type, re.IGNORECASE): + logging.debug('Using the OAI EPC HSS') + mySSH.command('cd ' + self.SourceCodePath, '\$', 5) + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd scripts', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) + elif re.match('ltebox', self.Type, re.IGNORECASE): + logging.debug('Using the ltebox simulated HSS') + mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5) + mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts', '\$', 5) + mySSH.command('cd /opt/hss_sim0609', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S rm -f hss.log', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S echo "Starting sudo session" && sudo su -c "screen -dm -S simulated_hss ./starthss"', '\$', 5) + 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) + + def InitializeMME(self): + 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) + if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 MME') + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) + mySSH.command('chmod 755 ./my-mme.sh', '\$', 5) + mySSH.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.SourceCodePath + '/scripts -o ' + self.SourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) + elif re.match('OAI', self.Type, re.IGNORECASE): + mySSH.command('cd ' + self.SourceCodePath, '\$', 5) + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd scripts', '\$', 5) + mySSH.command('stdbuf -o0 hostname', '\$', 5) + result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', mySSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') + sys.exit(1) + host_name = result.group('host_name') + mySSH.command('echo ' + self.Password + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) + elif re.match('ltebox', self.Type, re.IGNORECASE): + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S ./start_mme', '\$', 5) + 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) + + def InitializeSPGW(self): + 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) + if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) + mySSH.command('chmod 755 ./my-spgwc.sh', '\$', 5) + mySSH.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.SourceCodePath + '/scripts -o ' + self.SourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) + time.sleep(5) + mySSH.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) + mySSH.command('chmod 755 ./my-spgwu.sh', '\$', 5) + mySSH.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.SourceCodePath + '/scripts -o ' + self.SourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) + elif re.match('OAI', self.Type, re.IGNORECASE): + mySSH.command('cd ' + self.SourceCodePath, '\$', 5) + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd scripts', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) + elif re.match('ltebox', self.Type, re.IGNORECASE): + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S ./start_xGw', '\$', 5) + 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) + + def CheckHSSProcess(self, status_queue): + try: + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): + result = re.search('oai_hss -j', mySSH.getBefore()) + elif re.match('OAI', self.Type, re.IGNORECASE): + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + elif re.match('ltebox', self.Type, re.IGNORECASE): + result = re.search('hss_sim s6as diam_hss', mySSH.getBefore()) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m HSS Process Not Found! \u001B[0m') + status_queue.put(CONST.HSS_PROCESS_FAILED) + else: + status_queue.put(CONST.HSS_PROCESS_OK) + mySSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckMMEProcess(self, status_queue): + try: + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): + result = re.search('mme -c', mySSH.getBefore()) + elif re.match('OAI', self.Type, re.IGNORECASE): + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + elif re.match('ltebox', self.Type, re.IGNORECASE): + result = re.search('mme', mySSH.getBefore()) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m') + status_queue.put(CONST.MME_PROCESS_FAILED) + else: + status_queue.put(CONST.MME_PROCESS_OK) + mySSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckSPGWProcess(self, status_queue): + try: + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + if 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()) + elif re.match('OAI', self.Type, re.IGNORECASE): + mySSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + elif re.match('ltebox', self.Type, re.IGNORECASE): + mySSH.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) + result = re.search('xGw', mySSH.getBefore()) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m') + status_queue.put(CONST.SPGW_PROCESS_FAILED) + else: + status_queue.put(CONST.SPGW_PROCESS_OK) + mySSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def TerminateHSS(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + result = re.search('oai_hss -j', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) + mySSH.command('rm -f ' + self.SourceCodePath + '/scripts/my-hss.sh', '\$', 5) + elif re.match('OAI', self.Type, re.IGNORECASE): + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) + elif re.match('ltebox', self.Type, re.IGNORECASE): + mySSH.command('cd ' + self.SourceCodePath, '\$', 5) + mySSH.command('cd scripts', '\$', 5) + time.sleep(1) + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) + 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) + + def TerminateMME(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + if re.match('OAI', self.Type, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) + result = re.search('mme -c', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) + mySSH.command('rm -f ' + self.SourceCodePath + '/scripts/my-mme.sh', '\$', 5) + elif re.match('ltebox', self.Type, re.IGNORECASE): + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S ./stop_mme', '\$', 5) + 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) + + def TerminateSPGW(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + result = re.search('spgwc -c |spgwu -c ', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) + mySSH.command('rm -f ' + self.SourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) + mySSH.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) + result = re.search('-w ', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S chmod 666 ' + self.SourceCodePath + '/scripts/*.pcap', '\$', 5) + elif re.match('OAI', self.Type, re.IGNORECASE): + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.Password + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) + elif re.match('ltebox', self.Type, re.IGNORECASE): + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S ./stop_xGw', '\$', 5) + 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) + + def LogCollectHSS(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + mySSH.command('rm -f hss.log.zip', '\$', 5) + if 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) + if re.match('OAI-Rel14-CUPS', self.Type, re.IGNORECASE): + mySSH.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) + mySSH.command('echo ' + self.Password + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) + elif re.match('ltebox', self.Type, re.IGNORECASE): + mySSH.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) + mySSH.command('zip hss.log.zip hss.log', '\$', 60) + else: + logging.error('This option should not occur!') + mySSH.close() + + def LogCollectMME(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + mySSH.command('rm -f mme.log.zip', '\$', 5) + if 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) + elif re.match('ltebox', self.Type, re.IGNORECASE): + mySSH.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) + mySSH.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) + else: + logging.error('This option should not occur!') + mySSH.close() + + def LogCollectSPGW(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.IPAddress, self.UserName, self.Password) + mySSH.command('cd ' + self.SourceCodePath + '/scripts', '\$', 5) + mySSH.command('rm -f spgw.log.zip', '\$', 5) + if 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) + elif re.match('ltebox', self.Type, re.IGNORECASE): + mySSH.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) + mySSH.command('zip spgw.log.zip xGwLog.0', '\$', 60) + else: + logging.error('This option should not occur!') + mySSH.close() + diff --git a/ci-scripts/helpreadme.py b/ci-scripts/helpreadme.py new file mode 100644 index 0000000000..4b58c77510 --- /dev/null +++ b/ci-scripts/helpreadme.py @@ -0,0 +1,81 @@ +#/* +# * 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 +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Functions Declaration +#----------------------------------------------------------- + +def GenericHelp(vers): + print('----------------------------------------------------------------------------------------------------------------------') + print('main.py Ver: ' + vers) + print('----------------------------------------------------------------------------------------------------------------------') + print('python main.py [options]') + print(' --help Show this help.') + print(' --mode=[Mode]') + print(' TesteNB') + print(' InitiateHtml, FinalizeHtml') + print(' TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW') + print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') + +def GitSrvHelp(repository,branch,commit,mergeallow,targetbranch): + print(' --ranRepository=[OAI RAN Repository URL] -- ' + repository) + print(' --ranBranch=[OAI RAN Repository Branch] -- ' + branch) + print(' --ranCommitID=[OAI RAN Repository Commit SHA-1] -- ' + commit) + print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)] -- ' + mergeallow) + print(' --ranTargetBranch=[Target Branch in case of a Merge Request] -- ' + targetbranch) + +def eNBSrvHelp(ipaddr, username, password, sourcepath): + print(' --eNBIPAddress=[eNB\'s IP Address] -- ' + ipaddr) + print(' --eNBUserName=[eNB\'s Login User Name] -- ' + username) + print(' --eNBPassword=[eNB\'s Login Password] -- ' + password) + print(' --eNBSourceCodePath=[eNB\'s Source Code Path] -- ' + sourcepath) + +def OAIUESrvHelp(ipaddr, username, password, sourcepath): + print(' --UEIPAddress=[UE\'s IP Address] -- ' + ipaddr) + print(' --UEUserName=[UE\'s Login User Name] -- ' + username) + print(' --UEPassword=[UE\'s Login Password] -- ' + password) + print(' --UESourceCodePath=[UE\'s Source Code Path] -- ' + sourcepath) + +def EPCSrvHelp(ipaddr, username, password, sourcepath, epctype): + print(' --EPCIPAddress=[EPC\'s IP Address] -- ' + ipaddr) + print(' --EPCUserName=[EPC\'s Login User Name] -- ' + username) + print(' --EPCPassword=[EPC\'s Login Password] -- ' + password) + print(' --EPCSourceCodePath=[EPC\'s Source Code Path] -- ' + sourcepath) + print(' --EPCType=[EPC\'s Type: OAI or ltebox or OAI-Rel14-CUPS] -- ' + epctype) + +def ADBSrvHelp(ipaddr, username, password): + print(' --ADBIPAddress=[ADB\'s IP Address] -- ' + ipaddr) + print(' --ADBUserName=[ADB\'s Login User Name] -- ' + username) + print(' --ADBPassword=[ADB\'s Login Password] -- ' + password) + +def XmlHelp(filename): + print(' --XMLTestFile=[XML Test File to be run] -- ' + filename) + print(' Note: multiple xml files can be specified (--XMLFile=File1 ... --XMLTestFile=FileN) when HTML headers are created ("InitiateHtml" mode)') + diff --git a/ci-scripts/html.py b/ci-scripts/html.py new file mode 100644 index 0000000000..1a6e3f8fdb --- /dev/null +++ b/ci-scripts/html.py @@ -0,0 +1,479 @@ +#/* +# * 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 +import subprocess +from multiprocessing import Process, Lock, SimpleQueue + +import constants as CONST + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class HTMLManagement(): + + def __init__(self): + + self.htmlFile = '' + self.htmlHeaderCreated = False + self.htmlFooterCreated = False + + self.ranRepository = '' + self.ranBranch = '' + self.ranCommitID = '' + self.ranAllowMerge = False + self.ranTargetBranch = '' + + self.nbTestXMLfiles = 0 + self.htmlTabRefs = [] + self.htmlTabNames = [] + self.htmlTabIcons = [] + self.testXMLfiles = [] + + self.htmleNBFailureMsg = '' + self.htmlUEFailureMsg = '' + + self.startTime = int(round(time.time() * 1000)) + self.testCase_id = '' + self.desc = '' + + self.OsVersion = ['', ''] + self.KernelVersion = ['', ''] + self.UhdVersion = ['', ''] + self.UsrpBoard = ['', ''] + self.CpuNb = ['', ''] + self.CpuModel = ['', ''] + self.CpuMHz = ['', ''] + +#----------------------------------------------------------- +# Setters and Getters +#----------------------------------------------------------- + def SethtmlUEFailureMsg(self,huefa): + self.htmlUEFailureMsg = huefa + def GethtmlUEFailureMsg(self): + return self.htmlUEFailureMsg + def SetHmleNBFailureMsg(self, msg): + self.htmleNBFailureMsg = msg + + def Setdesc(self, dsc): + self.desc = dsc + + def SetstartTime(self, sttime): + self.startTime = sttime + + def SettestCase_id(self, tcid): + self.testCase_id = tcid + def GettestCase_id(self): + return self.testCase_id + + def SetranRepository(self, repository): + self.ranRepository = repository + def SetranAllowMerge(self, merge): + self.ranAllowMerge = merge + def SetranBranch(self, branch): + self.ranBranch = branch + def SetranCommitID(self, commitid): + self.ranCommitID = commitid + def SetranTargetBranch(self, tbranch): + self.ranTargetBranch = tbranch + + def SethtmlUEConnected(self, nbUEs): + if nbUEs > 0: + self.htmlUEConnected = nbUEs + else: + self.htmlUEConnected = 1 + def SethtmlNb_Smartphones(self, nbUEs): + self.htmlNb_Smartphones = nbUEs + def SethtmlNb_CATM_Modules(self, nbUEs): + self.htmlNb_CATM_Modules = nbUEs + + def SetnbTestXMLfiles(self, nb): + self.nbTestXMLfiles = nb + def GetnbTestXMLfiles(self): + return self.nbTestXMLfiles + + def SettestXMLfiles(self, xmlFile): + self.testXMLfiles.append(xmlFile) + def SethtmlTabRefs(self, tabRef): + self.htmlTabRefs.append(tabRef) + def SethtmlTabNames(self, tabName): + self.htmlTabNames.append(tabName) + def SethtmlTabIcons(self, tabIcon): + self.htmlTabIcons.append(tabIcon) + + def SetOsVersion(self, version, idx): + self.OsVersion[idx] = version + def SetKernelVersion(self, version, idx): + self.KernelVersion[idx] = version + def SetUhdVersion(self, version, idx): + self.UhdVersion[idx] = version + def SetUsrpBoard(self, version, idx): + self.UsrpBoard[idx] = version + def SetCpuNb(self, nb, idx): + self.CpuNb[idx] = nb + def SetCpuModel(self, model, idx): + self.CpuModel[idx] = model + def SetCpuMHz(self, freq, idx): + self.CpuMHz[idx] = freq + +#----------------------------------------------------------- +# HTML structure creation functions +#----------------------------------------------------------- + + + def CreateHtmlHeader(self, ADBIPAddress): + if (not self.htmlHeaderCreated): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML header \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + self.htmlFile = open('test_results.html', 'w') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') + self.htmlFile.write('\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if self.ranAllowMerge != '': + commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True) + commit_message = commit_message.strip() + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranTargetBranch == ''): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + self.ranRepository + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + self.ranBranch + '
Source Commit ID Commit ID ' + self.ranCommitID + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.ranTargetBranch + '
\n') + + if (ADBIPAddress != 'none'): + self.htmlFile.write('

' + str(self.htmlNb_Smartphones) + ' UE(s) is(are) connected to ADB bench server

\n') + self.htmlFile.write('

' + str(self.htmlNb_CATM_Modules) + ' CAT-M UE(s) is(are) connected to bench server

\n') + else: + self.htmlUEConnected = 1 + self.htmlFile.write('

1 OAI UE(s) is(are) connected to CI bench

\n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.close() + + def CreateHtmlTabHeader(self): + if (not self.htmlHeaderCreated): + if (not os.path.isfile('test_results.html')): + self.CreateHtmlHeader('none') + self.htmlFile = open('test_results.html', 'a') + if (self.nbTestXMLfiles == 1): + self.htmlFile.write('
\n') + self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') + else: + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' \n') + i += 1 + self.htmlFile.write(' \n') + self.htmlFile.close() + self.htmlHeaderCreated = True + + def CreateHtmlTabFooter(self, passStatus): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') + self.htmlFile.write('
\n') + self.htmlFile.close() + time.sleep(1) + if passStatus: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" + subprocess.run(cmd, shell=True) + else: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" + subprocess.run(cmd, shell=True) + self.htmlFooterCreated = False + + def CreateHtmlFooter(self, passStatus): + if (os.path.isfile('test_results.html')): + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write('
\n') + self.htmlFile.write('

\n') + self.htmlFile.write(' \n') + + machines = [ 'eNB', 'UE' ] + for machine in machines: + if machine == 'eNB': + idx = 0 + else: + idx = 1 + if self.OsVersion[idx] == '': + continue + + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
' + str('eNB') + ' Server Characteristics
OS Version' + self.OsVersion[idx] + 'Kernel Version' + self.KernelVersion[idx] + 'UHD Version' + self.UhdVersion[idx] + 'USRP Board' + self.UsrpBoard[idx] + '
Nb CPUs' + self.CpuNb[idx] + 'CPU Model Name' + self.CpuModel[idx] + 'CPU Frequency' + self.CpuMHz[idx] + '
Final StatusPASS FAIL
\n') + self.htmlFile.write('

\n') + self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('\n') + self.htmlFile.close() + + def CreateHtmlRetrySeparator(self, cntnumfails): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write(' \n') + self.htmlFile.write(' ---- Try Run #' + str(cntnumfails) + ' ---- \n') + self.htmlFile.write(' \n') + self.htmlFile.close() + + def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): + if (self.htmlFooterCreated or (not self.htmlHeaderCreated)): + return + self.htmlFile = open('test_results.html', 'a') + currentTime = int(round(time.time() * 1000)) - self.startTime + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + if (processesStatus == 0): + self.htmlFile.write(' ' + str(status) + '\n') + elif (processesStatus == CONST.ENB_PROCESS_FAILED): + self.htmlFile.write(' KO - eNB process not found\n') + elif (processesStatus == CONST.OAI_UE_PROCESS_FAILED): + self.htmlFile.write(' KO - OAI UE process not found\n') + elif (processesStatus == CONST.ENB_PROCESS_SEG_FAULT) or (processesStatus == CONST.OAI_UE_PROCESS_SEG_FAULT): + self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') + elif (processesStatus == CONST.ENB_PROCESS_ASSERTION) or (processesStatus == CONST.OAI_UE_PROCESS_ASSERTION): + self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') + elif (processesStatus == CONST.ENB_PROCESS_REALTIME_ISSUE): + self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') + elif (processesStatus == CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): + self.htmlFile.write(' OK?\n') + elif (processesStatus == CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): + self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') + elif (processesStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC): + self.htmlFile.write(' KO - UE could not sync\n') + elif (processesStatus == CONST.HSS_PROCESS_FAILED): + self.htmlFile.write(' KO - HSS process not found\n') + elif (processesStatus == CONST.MME_PROCESS_FAILED): + self.htmlFile.write(' KO - MME process not found\n') + elif (processesStatus == CONST.SPGW_PROCESS_FAILED): + self.htmlFile.write(' KO - SPGW process not found\n') + elif (processesStatus == CONST.UE_IP_ADDRESS_ISSUE): + self.htmlFile.write(' KO - Could not retrieve UE IP address\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + if (len(str(self.htmleNBFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') + self.htmleNBFailureMsg = '' + elif (len(str(self.htmlUEFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') + self.htmlUEFailureMsg = '' + else: + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + self.htmlFile.close() + + def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile = open('test_results.html', 'a') + currentTime = int(round(time.time() * 1000)) - self.startTime + addOrangeBK = False + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + self.htmlFile.write(' ' + str(status) + '\n') + else: + addOrangeBK = True + self.htmlFile.write(' ' + str(status) + '\n') + i = 0 + while (i < self.htmlUEConnected): + if (i < ue_status): + if (not ue_queue.empty()): + if (addOrangeBK): + self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') + else: + self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') + else: + self.htmlFile.write(' -\n') + else: + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + self.htmlFile.close() + diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 21d51105f8..a01eed2ac5 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -1,4 +1,4 @@ -#/* + # * 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. @@ -28,47 +28,7 @@ # pexpect #--------------------------------------------------------------------- -#----------------------------------------------------------- -# Version -#----------------------------------------------------------- -Version = '0.1' - -#----------------------------------------------------------- -# Constants -#----------------------------------------------------------- -ALL_PROCESSES_OK = 0 -ENB_PROCESS_FAILED = -1 -ENB_PROCESS_OK = +1 -ENB_PROCESS_SEG_FAULT = -11 -ENB_PROCESS_ASSERTION = -12 -ENB_PROCESS_REALTIME_ISSUE = -13 -ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 -ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 -HSS_PROCESS_FAILED = -2 -HSS_PROCESS_OK = +2 -MME_PROCESS_FAILED = -3 -MME_PROCESS_OK = +3 -SPGW_PROCESS_FAILED = -4 -SPGW_PROCESS_OK = +4 -UE_IP_ADDRESS_ISSUE = -5 -OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 -OAI_UE_PROCESS_COULD_NOT_SYNC = -21 -OAI_UE_PROCESS_ASSERTION = -22 -OAI_UE_PROCESS_FAILED = -23 -OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 -OAI_UE_PROCESS_SEG_FAULT = -25 -OAI_UE_PROCESS_OK = +6 - -UE_STATUS_DETACHED = 0 -UE_STATUS_DETACHING = 1 -UE_STATUS_ATTACHING = 2 -UE_STATUS_ATTACHED = 3 - -X2_HO_REQ_STATE__IDLE = 0 -X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 -X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 -X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 -X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 +import constants as CONST #----------------------------------------------------------- # Import @@ -89,55 +49,27 @@ logging.basicConfig( format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" ) + #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- -class SSHConnection(): +class OaiCiTest(): + def __init__(self): - self.prematureExit = False self.ranRepository = '' self.ranBranch = '' - self.ranAllowMerge = False self.ranCommitID = '' + self.ranAllowMerge = False self.ranTargetBranch = '' - self.eNBIPAddress = '' - self.eNBUserName = '' - self.eNBPassword = '' - self.eNBSourceCodePath = '' - self.EPCIPAddress = '' - self.EPCUserName = '' - self.EPCPassword = '' - self.eNB1IPAddress = '' - self.eNB1UserName = '' - self.eNB1Password = '' - self.eNB1SourceCodePath = '' - self.eNB2IPAddress = '' - self.eNB2UserName = '' - self.eNB2Password = '' - self.eNB2SourceCodePath = '' - self.EPCSourceCodePath = '' - self.EPCType = '' - self.EPC_PcapFileName = '' + + self.FailReportCnt = 0 self.ADBIPAddress = '' self.ADBUserName = '' self.ADBPassword = '' self.ADBCentralized = True self.testCase_id = '' self.testXMLfiles = [] - self.nbTestXMLfiles = 0 self.desc = '' - self.Build_eNB_args = '' - self.backgroundBuild = False - self.backgroundBuildTestId = ['', '', ''] - self.Build_eNB_forced_workspace_cleanup = False - self.Initialize_eNB_args = '' - self.air_interface = 'lte' - self.eNB_instance = '' - self.eNB_serverId = '' - self.eNBLogFiles = ['', '', ''] - self.eNBOptions = ['', '', ''] - self.eNBmbmsEnables = [False, False, False] - self.eNBstatuses = [-1, -1, -1] self.ping_args = '' self.ping_packetloss_threshold = '' self.iperf_args = '' @@ -154,30 +86,13 @@ class SSHConnection(): self.UEDevicesRebootCmd = [] self.CatMDevices = [] self.UEIPAddresses = [] - self.htmlFile = '' - self.htmlHeaderCreated = False - self.htmlFooterCreated = False - self.htmlUEConnected = -1 - self.htmleNBFailureMsg = '' - self.htmlUEFailureMsg = '' - self.picocom_closure = False self.idle_sleep_time = 0 self.x2_ho_options = 'network' self.x2NbENBs = 0 self.x2ENBBsIds = [] self.x2ENBConnectedUEs = [] - self.htmlTabRefs = [] - self.htmlTabNames = [] - self.htmlTabIcons = [] self.repeatCounts = [] self.finalStatus = False - self.OsVersion = '' - self.KernelVersion = '' - self.UhdVersion = '' - self.UsrpBoard = '' - self.CpuNb = '' - self.CpuModel = '' - self.CpuMHz = '' self.UEIPAddress = '' self.UEUserName = '' self.UEPassword = '' @@ -187,819 +102,192 @@ class SSHConnection(): self.Build_OAI_UE_args = '' self.Initialize_OAI_UE_args = '' self.clean_repository = True - self.flexranCtrlInstalled = False - self.flexranCtrlStarted = False self.expectedNbOfConnectedUEs = 0 - self.startTime = 0 - - def open(self, ipaddress, username, password): - count = 0 - connect_status = False - while count < 4: - self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress], timeout = 5) - self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - self.ssh.sendline('yes') - self.ssh.expect('password:') - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 1: - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 2: - # Checking if we are really on the remote client defined by its IP address - self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) - result = re.search(str(ipaddress), str(self.ssh.before)) - if result is None: - self.close() - else: - count = 10 - connect_status = True - else: - # debug output - logging.debug(str(self.ssh.before)) - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - # adding a tempo when failure - if not connect_status: - time.sleep(1) - count += 1 - if connect_status: - pass - else: - sys.exit('SSH Connection Failed') - - def command(self, commandline, expectedline, timeout): - logging.debug(commandline) - self.ssh.timeout = timeout - self.ssh.sendline(commandline) - self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - return 0 - elif self.sshresponse == 1: - logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - logging.debug(str(self.ssh.before)) - sys.exit(self.sshresponse) - elif self.sshresponse == 2: - logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - result = re.search('ping |iperf |picocom', str(commandline)) - if result is None: - logging.debug(str(self.ssh.before)) - sys.exit(self.sshresponse) - else: - return -1 - else: - logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - sys.exit(self.sshresponse) - - def close(self): - self.ssh.timeout = 5 - self.ssh.sendline('exit') - self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - pass - elif self.sshresponse == 1: - if not self.picocom_closure: - logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') - else: - logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') - - def copyin(self, ipaddress, username, password, source, destination): - count = 0 - copy_status = False - logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination) - while count < 10: - scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - else: - logging.debug('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.debug('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - return 0 - else: - return -1 - - def copyout(self, ipaddress, username, password, source, destination): - count = 0 - copy_status = False - logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination) - while count < 4: - scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - else: - logging.debug('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.debug('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - pass - else: - sys.exit('SCP failed') - - def BuildeNB(self): - if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': - Usage() - sys.exit('Insufficient Parameter') - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - result = re.search('--gNB', self.Build_eNB_args) - if result is not None: - self.air_interface = 'nr' - else: - self.air_interface = 'lte' - if self.Build_eNB_forced_workspace_cleanup: - self.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) - 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' - self.command('mkdir -p ' + lSourcePath, '\$', 5) - self.command('cd ' + lSourcePath, '\$', 5) - self.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 - self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - self.command('git config user.name "OAI Jenkins"', '\$', 5) - # Checking the BUILD INFO file - if not self.backgroundBuild: - self.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) - if result is not None: - mismatch = False - self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - result = re.search('YES', str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - result = re.search('develop', str(self.ssh.before)) - else: - result = re.search(self.ranTargetBranch, str(self.ssh.before)) - if result is None: - mismatch = True - else: - result = re.search('NO', str(self.ssh.before)) - if result is None: - mismatch = True - if not mismatch: - self.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - return - - self.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) - # if the commit ID is provided use it to point to it - if self.ranCommitID != '': - self.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 - if (self.ranAllowMerge): - if self.ranTargetBranch == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('mkdir -p log', '\$', 5) - self.command('chmod 777 log', '\$', 5) - # no need to remove in log (git clean did the trick) - if self.backgroundBuild: - self.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) - self.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) - self.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id - return - self.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) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) - - def WaitBuildeNBisFinished(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - count = 40 - buildOAIprocess = True - while (count > 0) and buildOAIprocess: - self.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) - result = re.search('build_oai', str(self.ssh.before)) - if result is None: - buildOAIprocess = False - else: - count -= 1 - time.sleep(30) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) - - def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): - self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) - self.command('ls ran_build/build', '\$', 3) - self.command('ls ran_build/build', '\$', 3) - if self.air_interface == 'nr': - nodeB_prefix = 'g' - else: - nodeB_prefix = 'e' - buildStatus = True - result = re.search(self.air_interface + '-softmodem', str(self.ssh.before)) - if result is None: - buildStatus = False - else: - # Generating a BUILD INFO file - self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('mkdir -p build_log_' + testcaseId, '\$', 5) - self.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) - self.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) - if self.eNB_serverId != '0': - self.command('cd cmake_targets', '\$', 5) - self.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) - self.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) - self.close() - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - os.remove('./tmp_build' + testcaseId + '.zip') - self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') - os.remove('./tmp_build' + testcaseId + '.zip') - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) - self.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) - self.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) - self.close() - else: - self.close() - - if buildStatus: - logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - else: - logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) - self.CreateHtmlTabFooter(False) - sys.exit(1) def BuildOAIUE(self): if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) result = re.search('--nrUE', self.Build_OAI_UE_args) if result is not None: - self.air_interface = 'nr' + RAN.Setair_interface('nr') ue_prefix = 'NR ' else: - self.air_interface = 'lte' + RAN.Setair_interface('lte') ue_prefix = '' 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' - self.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + SSH.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) # here add a check if git clone or git fetch went smoothly - self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - self.command('git config user.name "OAI Jenkins"', '\$', 5) + SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + SSH.command('git config user.name "OAI Jenkins"', '\$', 5) if self.clean_repository: - self.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) + SSH.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', SSH.getBefore()) if result is not None: mismatch = False - self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, str(self.ssh.before)) + SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(self.ranCommitID, SSH.getBefore()) if result is None: mismatch = True - self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - result = re.search('YES', str(self.ssh.before)) + SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if self.ranAllowMerge: + result = re.search('YES', SSH.getBefore()) if result is None: mismatch = True - self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if self.ranTargetBranch == '': - result = re.search('develop', str(self.ssh.before)) + result = re.search('develop', SSH.getBefore()) else: - result = re.search(self.ranTargetBranch, str(self.ssh.before)) + result = re.search(self.ranTargetBranch, SSH.getBefore()) if result is None: mismatch = True else: - result = re.search('NO', str(self.ssh.before)) + result = re.search('NO', SSH.getBefore()) if result is None: mismatch = True if not mismatch: - self.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + SSH.close() + HTML.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', CONST.ALL_PROCESSES_OK) return - self.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) + SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) # if the commit ID is provided use it to point to it if self.ranCommitID != '': - self.command('git checkout -f ' + self.ranCommitID, '\$', 5) + SSH.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 - if (self.ranAllowMerge): + if self.ranAllowMerge: if self.ranTargetBranch == '': if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) else: logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('mkdir -p log', '\$', 5) - self.command('chmod 777 log', '\$', 5) + SSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('mkdir -p log', '\$', 5) + SSH.command('chmod 777 log', '\$', 5) # no need to remove in log (git clean did the trick) - self.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 600) - self.command('ls ran_build/build', '\$', 3) - self.command('ls ran_build/build', '\$', 3) + 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', 600) + SSH.command('ls ran_build/build', '\$', 3) + SSH.command('ls ran_build/build', '\$', 3) buildStatus = True - result = re.search(self.air_interface + '-uesoftmodem', str(self.ssh.before)) + result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) if result is None: buildStatus = False - self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) - self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) - self.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) + SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + SSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + SSH.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) if buildStatus: # Generating a BUILD INFO file - self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranAllowMerge: + SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) if self.ranTargetBranch == '': - self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: - self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: - self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - self.close() - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.close() + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') else: - self.close() + SSH.close() logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', CONST.ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTabFooter(False) sys.exit(1) - - def InitializeHSS(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') - EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) - self.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) - self.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) - self.command('chmod 755 ./my-hss.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC HSS') - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - logging.debug('Using the ltebox simulated HSS') - self.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - self.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('cd /opt/hss_sim0609', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) - # based on Robert's feedback, new method to run simulated HSS - self.command('sudo su -c "cd /opt/hss_sim0609 && screen -dm -S simulated_hss ./starthss_real"', '\$', 5) - else: - logging.error('This option should not occur!') - self.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - - def InitializeMME(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 MME') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) - self.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) - self.command('chmod 755 ./my-mme.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('stdbuf -o0 hostname', '\$', 5) - result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') - sys.exit(1) - host_name = result.group('host_name') - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) - else: - logging.error('This option should not occur!') - self.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - - def InitializeSPGW(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) - self.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) - self.command('chmod 755 ./my-spgwc.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) - time.sleep(5) - self.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) - self.command('chmod 755 ./my-spgwu.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) - else: - logging.error('This option should not occur!') - self.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - + def CheckFlexranCtrlInstallation(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': return - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) - result = re.search('/opt/flexran_rtc/build/rt_controller', str(self.ssh.before)) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) + result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) if result is not None: - self.flexranCtrlInstalled = True + RAN.SetflexranCtrlInstalled(True) logging.debug('Flexran Controller is installed') - self.close() + SSH.close() def InitializeFlexranCtrl(self): - if self.flexranCtrlInstalled == False: + if RAN.GetflexranCtrlInstalled() == False: return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd /opt/flexran_rtc', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) - self.command('ps -aux | grep --color=never rt_controller', '\$', 5) - result = re.search('rt_controller -c ', str(self.ssh.before)) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd /opt/flexran_rtc', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f log/*.log', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) + SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) + result = re.search('rt_controller -c ', SSH.getBefore()) if result is not None: logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') - self.flexranCtrlStarted = True - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def InitializeeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = False - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus) - self.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: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.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', str(self.ssh.before)) - if result is not None: - eth_interface = result.group('eth_interface') - logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') - self.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) - self.close() - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath, '\$', 5) - # Initialize_eNB_args usually start with -O and followed by the location in repository - full_config_file = self.Initialize_eNB_args.replace('-O ','') - extra_options = '' - extIdx = full_config_file.find('.conf') - if (extIdx > 0): - extra_options = full_config_file[extIdx + 5:] - # if tracer options is on, compiling and running T Tracer - result = re.search('T_stdout', str(extra_options)) - if result is not None: - logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') - self.command('cd common/utils/T/tracer', '\$', 5) - self.command('make', '\$', 10) - self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) - self.command('cd ' + lSourcePath, '\$', 5) - full_config_file = full_config_file[:extIdx + 5] - config_path, config_file = os.path.split(full_config_file) - else: - sys.exit('Insufficient Parameter') - ci_full_config_file = config_path + '/ci-' + config_file - rruCheck = False - result = re.search('^rru|^rcc|^du.band', str(config_file)) - if result is not None: - rruCheck = True - # do not reset board twice in IF4.5 case - result = re.search('^rru|^enb|^du.band', str(config_file)) - if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) - result = re.search('type: b200', str(self.ssh.before)) - if result is not None: - logging.debug('Found a B2xx device --> resetting it') - self.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) - # Reloading FGPA bin firmware - self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) - # Make a copy and adapt to EPC / eNB IP addresses - self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - self.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); - else: - self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); - self.eNBmbmsEnables[int(self.eNB_instance)] = False - self.command('grep enable_enb_m2 ' + ci_full_config_file, '\$', 2); - result = re.search('yes', str(self.ssh.before)) - if result is not None: - self.eNBmbmsEnables[int(self.eNB_instance)] = True - logging.debug('\u001B[1m MBMS is enabled on this eNB\u001B[0m') - result = re.search('noS1', str(self.Initialize_eNB_args)) - eNBinNoS1 = False - if result is not None: - eNBinNoS1 = True - logging.debug('\u001B[1m eNB is in noS1 configuration \u001B[0m') - # Launch eNB with the modified config file - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) - self.command('hostnamectl','\$', 5) - result = re.search('CentOS Linux 7', str(self.ssh.before)) - if result is not None: - self.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) - else: - self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' - if extra_options != '': - self.eNBOptions[int(self.eNB_instance)] = extra_options - time.sleep(6) - doLoop = True - loopCounter = 20 - enbDidSync = False - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # In case of T tracer recording, we may need to kill it - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - self.command('killall --signal SIGKILL record', '\$', 5) - self.close() - doLoop = False - logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', 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: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - if self.EPC_PcapFileName != '': - time.sleep(0.5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.close() - time.sleep(1) - if self.EPC_PcapFileName != '': - copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') - if (copyin_res == 0): - self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') - self.prematureExit = True - return - else: - self.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) - if rruCheck: - result = re.search('wait RUs', str(self.ssh.before)) - else: - result = re.search('got sync|Starting F1AP at CU', str(self.ssh.before)) - if result is None: - time.sleep(6) - else: - doLoop = False - enbDidSync = True - time.sleep(10) - - if enbDidSync and eNBinNoS1: - self.command('ifconfig oaitun_enb1', '\$', 4) - self.command('ifconfig oaitun_enb1', '\$', 4) - result = re.search('inet addr:1|inet 1', str(self.ssh.before)) - if result is not None: - logging.debug('\u001B[1m oaitun_enb1 interface is mounted and configured\u001B[0m') - else: - logging.error('\u001B[1m oaitun_enb1 interface is either NOT mounted or NOT configured\u001B[0m') - if self.eNBmbmsEnables[int(self.eNB_instance)]: - self.command('ifconfig oaitun_enm1', '\$', 4) - result = re.search('inet addr', str(self.ssh.before)) - if result is not None: - logging.debug('\u001B[1m oaitun_enm1 interface is mounted and configured\u001B[0m') - 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.close() - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) - logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') - + RAN.SetflexranCtrlStarted(True) + SSH.close() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + def InitializeUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if not self.ADBCentralized: # Reboot UE - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) # Wait #time.sleep(60) # Put in LTE-Mode only - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) # enable data service - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) # we need to do radio on/off cycle to make sure of above changes # airplane mode off // radio on - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) #time.sleep(10) # airplane mode on // radio off - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) # normal procedure without reboot # enable data service - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) # airplane mode on // radio off - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - self.close() + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.close() return # enable data service - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) # The following commands are deprecated since we no longer work on Android 7+ - # self.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) - # self.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) # a dedicated script has to be installed inside the UE # airplane mode on means call /data/local/tmp/off if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) #airplane mode off means call /data/local/tmp/on logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def InitializeUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') multi_jobs = [] i = 0 @@ -1011,62 +299,62 @@ class SSHConnection(): i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def InitializeOAIUE(self): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - if self.air_interface == 'lte': + if RAN.Getair_interface() == 'lte': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) if result is None: check_eNB = True check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) UE_prefix = '' else: UE_prefix = 'NR ' - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) # b2xx_fx3_utils reset procedure - self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 60) - result = re.search('type: b200', str(self.ssh.before)) + SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 60) + result = re.search('type: b200', SSH.getBefore()) if result is not None: logging.debug('Found a B2xx device --> resetting it') - self.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + SSH.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) # Reloading FGPA bin firmware - self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 60) - result = re.search('type: n3xx', str(self.ssh.before)) + SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 60) + result = re.search('type: n3xx', str(SSH.getBefore())) if result is not None: logging.debug('Found a N3xx device --> resetting it') - self.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) # Initialize_OAI_UE_args usually start with -C and followed by the location in repository # in case of NR-UE, we may have rrc_config_path (Temporary?) modifiedUeOptions = str(self.Initialize_OAI_UE_args) - if self.air_interface == 'nr': + if RAN.Getair_interface() == 'nr': result = re.search('--rrc_config_path ', modifiedUeOptions) if result is not None: modifiedUeOptions = modifiedUeOptions.replace('rrc_config_path ', 'rrc_config_path ' + self.UESourceCodePath + '/') - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets/ran_build/build', '\$', 5) - if self.air_interface == 'lte': + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets/ran_build/build', '\$', 5) + if RAN.Getair_interface() == 'lte': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) # We may have to regenerate the .u* files if result is None: - self.command('ls /tmp/*.sed', '\$', 5) - result = re.search('adapt_usim_parameters', str(self.ssh.before)) + SSH.command('ls /tmp/*.sed', '\$', 5) + result = re.search('adapt_usim_parameters', SSH.getBefore()) if result is not None: - self.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + SSH.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) else: - self.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) - self.command('echo "ulimit -c unlimited && ./'+ self.air_interface +'-uesoftmodem ' + modifiedUeOptions + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) + SSH.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) + SSH.command('echo "ulimit -c unlimited && ./'+ RAN.Getair_interface() +'-uesoftmodem ' + modifiedUeOptions + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) self.UELogFile = 'ue_' + self.testCase_id + '.log' # We are now looping several times to hope we really sync w/ an eNB @@ -1075,13 +363,13 @@ class SSHConnection(): gotSyncStatus = True fullSyncStatus = True while (doOutterLoop): - self.command('cd ' + self.UESourceCodePath + '/cmake_targets/ran_build/build', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/ran_build/build', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) #use nohup instead of daemon - #self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/ran_build/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.command('echo $USER; nohup sudo ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5) + #SSH.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/ran_build/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo $USER; nohup sudo ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5) time.sleep(6) - self.command('cd ../..', '\$', 5) + SSH.command('cd ../..', '\$', 5) doLoop = True loopCounter = 10 gotSyncStatus = True @@ -1094,11 +382,11 @@ class SSHConnection(): gotSyncStatus = False doLoop = False continue - self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - if self.air_interface == 'nr': - result = re.search('Starting sync detection', str(self.ssh.before)) + SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + if RAN.Getair_interface() == 'nr': + result = re.search('Starting sync detection', SSH.getBefore()) else: - result = re.search('got sync', str(self.ssh.before)) + result = re.search('got sync', SSH.getBefore()) if result is None: time.sleep(10) else: @@ -1106,16 +394,16 @@ class SSHConnection(): logging.debug('Found "got sync" message!') if gotSyncStatus == False: # we certainly need to stop the lte-uesoftmodem process if it is still running! - self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('-uesoftmodem', str(self.ssh.before)) + SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('-uesoftmodem', SSH.getBefore()) if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT -r *-uesoftmodem', '\$', 4) + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT -r *-uesoftmodem', '\$', 4) time.sleep(3) outterLoopCounter = outterLoopCounter - 1 if (outterLoopCounter == 0): doOutterLoop = False continue - if self.air_interface == 'nr': + if RAN.Getair_interface() == 'nr': fullSyncStatus = True doOutterLoop = False else: @@ -1131,8 +419,8 @@ class SSHConnection(): doOutterLoop = False fullSyncStatus = True continue - self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - result = re.search('No cell synchronization found', str(self.ssh.before)) + SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + result = re.search('No cell synchronization found', SSH.getBefore()) if result is None: time.sleep(6) else: @@ -1140,31 +428,31 @@ class SSHConnection(): fullSyncStatus = False logging.debug('Found: "No cell synchronization" message! --> try again') time.sleep(6) - self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) + SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('lte-uesoftmodem', SSH.getBefore()) if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) outterLoopCounter = outterLoopCounter - 1 if (outterLoopCounter == 0): doOutterLoop = False - if fullSyncStatus and gotSyncStatus and self.air_interface == 'lte': + if fullSyncStatus and gotSyncStatus and RAN.Getair_interface() == 'lte': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) if result is None: - self.command('ifconfig oaitun_ue1', '\$', 4) - self.command('ifconfig oaitun_ue1', '\$', 4) + SSH.command('ifconfig oaitun_ue1', '\$', 4) + SSH.command('ifconfig oaitun_ue1', '\$', 4) # ifconfig output is different between ubuntu 16 and ubuntu 18 - result = re.search('inet addr:1|inet 1', str(self.ssh.before)) + result = re.search('inet addr:1|inet 1', SSH.getBefore()) if result is not None: logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') tunnelInterfaceStatus = True else: - logging.debug(str(self.ssh.before)) + logging.debug(SSH.getBefore()) logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') tunnelInterfaceStatus = False - if self.eNBmbmsEnables[0]: - self.command('ifconfig oaitun_uem1', '\$', 4) - result = re.search('inet addr', str(self.ssh.before)) + if RAN.GeteNBmbmsEnable(0): + SSH.command('ifconfig oaitun_uem1', '\$', 4) + result = re.search('inet addr', SSH.getBefore()) if result is not None: logging.debug('\u001B[1m oaitun_uem1 interface is mounted and configured\u001B[0m') tunnelInterfaceStatus = tunnelInterfaceStatus and True @@ -1176,116 +464,116 @@ class SSHConnection(): else: tunnelInterfaceStatus = True - self.close() + SSH.close() if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') if (self.ADBIPAddress != 'none'): self.UEDevices = [] self.UEDevices.append('OAI-UE') self.UEDevicesStatus = [] - self.UEDevicesStatus.append(UE_STATUS_DETACHED) + self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) else: - if self.air_interface == 'lte': - if self.eNBmbmsEnables[0]: - self.htmlUEFailureMsg = 'oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' + if RAN.Getair_interface() == 'lte': + if RAN.GeteNBmbmsEnable(0): + HTML.SethtmlUEFailureMsg('oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured') else: - self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') + HTML.SethtmlUEFailureMsg('oaitun_ue1 interface is either NOT mounted or NOT configured') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') else: - self.htmlUEFailureMsg = 'nr-uesoftmodem did NOT synced' - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') + HTML.SethtmlUEFailureMsg('nr-uesoftmodem did NOT synced') + HTML.CreateHtmlTestRow(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() def checkDevTTYisUnlocked(self): - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) count = 0 while count < 5: - self.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) - result = re.search('picocom', str(self.ssh.before)) + SSH.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) + result = re.search('picocom', SSH.getBefore()) if result is None: count = 10 else: time.sleep(5) count = count + 1 - self.close() + SSH.close() def InitializeCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.enablePicocomClosure() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) time.sleep(1) # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) # Doing a power cycle - self.command('AT^RESET', 'SIMSTORE,READY', 15) - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - self.command('ATE1', 'OK', 5) + SSH.command('AT^RESET', 'SIMSTORE,READY', 15) + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) + SSH.command('ATE1', 'OK', 5) # Disabling the Radio - self.command('AT+CFUN=0', 'OK', 5) + SSH.command('AT+CFUN=0', 'OK', 5) logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') # Checking if auto-attach is enabled - self.command('AT^AUTOATT?', 'OK', 5) - result = re.search('AUTOATT: (?P[0-9\-]+)', str(self.ssh.before)) + SSH.command('AT^AUTOATT?', 'OK', 5) + result = re.search('AUTOATT: (?P[0-9\-]+)', SSH.getBefore()) if result is not None: if result.group('state') is not None: autoAttachState = int(result.group('state')) if autoAttachState is not None: if autoAttachState == 0: - self.command('AT^AUTOATT=1', 'OK', 5) + SSH.command('AT^AUTOATT=1', 'OK', 5) logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') else: logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') # Force closure of picocom but device might still be locked - self.close() - self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + SSH.close() + SSH.disablePicocomClosure() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() def TerminateCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.enablePicocomClosure() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) time.sleep(1) # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) # Disabling the Radio - self.command('AT+CFUN=0', 'OK', 5) + SSH.command('AT+CFUN=0', 'OK', 5) logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - self.close() - self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + SSH.close() + SSH.disablePicocomClosure() + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() def AttachCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.enablePicocomClosure() + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) time.sleep(1) # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) # Enabling the Radio - self.command('AT+CFUN=1', 'SIMSTORE,READY', 5) + SSH.command('AT+CFUN=1', 'SIMSTORE,READY', 5) logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') time.sleep(4) # We should check if we register @@ -1293,15 +581,15 @@ class SSHConnection(): attach_cnt = 0 attach_status = False while count < 5: - self.command('AT+CEREG?', 'OK', 5) - result = re.search('CEREG: 2,(?P[0-9\-]+),', str(self.ssh.before)) + SSH.command('AT+CEREG?', 'OK', 5) + result = re.search('CEREG: 2,(?P[0-9\-]+),', SSH.getBefore()) if result is not None: mDataConnectionState = int(result.group('state')) if mDataConnectionState is not None: if mDataConnectionState == 1: count = 10 attach_status = True - result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', str(self.ssh.before)) + result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', SSH.getBefore()) if result is not None: networky = result.group('networky') networkz = result.group('networkz') @@ -1312,21 +600,21 @@ class SSHConnection(): logging.debug('+CEREG: 2,' + str(mDataConnectionState)) attach_cnt = attach_cnt + 1 else: - logging.debug(str(self.ssh.before)) + logging.debug(SSH.getBefore()) attach_cnt = attach_cnt + 1 count = count + 1 time.sleep(1) if attach_status: - self.command('AT+CESQ', 'OK', 5) - result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', str(self.ssh.before)) + SSH.command('AT+CESQ', 'OK', 5) + result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', SSH.getBefore()) if result is not None: nRSRQ = int(result.group('rsrq')) nRSRP = int(result.group('rsrp')) if (nRSRQ is not None) and (nRSRP is not None): logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') - self.close() - self.picocom_closure = False + SSH.close() + SSH.disablePicocomClosure() html_queue = SimpleQueue() self.checkDevTTYisUnlocked() if attach_status: @@ -1337,74 +625,74 @@ class SSHConnection(): else: html_cell += '' html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) else: logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') html_cell = '
CAT-M module Attachment Failed
' html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) self.AutoTerminateUEandeNB() def PingCatM(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return try: statusQueue = SimpleQueue() lock = Lock() - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE): + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.command('cd scripts', '\$', 5) + if re.match('OAI', EPC.GetType(), re.IGNORECASE): logging.debug('Using the OAI EPC HSS: not implemented yet') - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) else: - self.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) - result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', str(self.ssh.before)) + SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) + result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', SSH.getBefore()) if result is not None: moduleIPAddr = result.group('ipaddr') else: - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ping_time = re.findall("-c (\d+)",str(self.ping_args)) device_id = 'catm' - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) if result is None: message = 'Packet Loss Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return packetloss = result.group('packetloss') if float(packetloss) == 100: message = 'Packet Loss is 100%' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) if result is None: message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return rtt_min = result.group('rtt_min') @@ -1431,37 +719,37 @@ class SSHConnection(): qMsg += '\nPacket Loss is not 0%' logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') lock.release() - self.close() + SSH.close() html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' statusQueue.put(html_cell) if (packetLossOK): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) self.AutoTerminateUEandeNB() except: os.kill(os.getppid(),signal.SIGUSR1) def AttachUE_common(self, device_id, statusQueue, lock, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) else: # airplane mode off // radio on - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) time.sleep(2) max_count = 45 count = max_count while count > 0: if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') lock.acquire() @@ -1484,19 +772,19 @@ class SSHConnection(): logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) time.sleep(0.5) if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) time.sleep(0.5) logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') time.sleep(1) @@ -1507,19 +795,19 @@ class SSHConnection(): statusQueue.put(device_id) statusQueue.put('Attach Failed') lock.release() - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def AttachUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) self.AutoTerminateUEandeNB() return multi_jobs = [] @@ -1528,7 +816,7 @@ class SSHConnection(): nb_ue_to_connect = 0 for device_id in self.UEDevices: if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): - self.UEDevicesStatus[nb_ue_to_connect] = UE_STATUS_ATTACHING + self.UEDevicesStatus[nb_ue_to_connect] = CONST.UE_STATUS_ATTACHING p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) p.daemon = True p.start() @@ -1538,7 +826,7 @@ class SSHConnection(): job.join() if (status_queue.empty()): - self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() return else: @@ -1558,48 +846,48 @@ class SSHConnection(): if (attach_status): cnt = 0 while cnt < len(self.UEDevices): - if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING: - self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED + if self.UEDevicesStatus[cnt] == CONST.UE_STATUS_ATTACHING: + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_ATTACHED cnt += 1 - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - result = re.search('T_stdout', str(self.Initialize_eNB_args)) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) else: - self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def DetachUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def DetachUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) self.AutoTerminateUEandeNB() return multi_jobs = [] cnt = 0 for device_id in self.UEDevices: - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHING + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHING p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) p.daemon = True p.start() @@ -1607,37 +895,37 @@ class SSHConnection(): cnt += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - result = re.search('T_stdout', str(self.Initialize_eNB_args)) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) cnt = 0 while cnt < len(self.UEDevices): - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHED + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHED cnt += 1 def RebootUE_common(self, device_id): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) previousmDataConnectionStates = [] # Save mDataConnectionState - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') sys.exit(1) previousmDataConnectionStates.append(int(result.group('state'))) # Reboot UE - self.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) time.sleep(60) previousmDataConnectionState = previousmDataConnectionStates.pop(0) count = 180 while count > 0: count = count - 1 - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) if result is None: mDataConnectionState = None else: @@ -1652,20 +940,20 @@ class SSHConnection(): if count == 0: logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') sys.exit(1) - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def RebootUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] for device_id in self.UEDevices: @@ -1675,24 +963,24 @@ class SSHConnection(): multi_jobs.append(p) for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def DataDisableUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # disable data service if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def DataDisableUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') multi_jobs = [] i = 0 @@ -1704,24 +992,24 @@ class SSHConnection(): i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def DataEnableUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # enable data service if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def DataEnableUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') multi_jobs = [] i = 0 @@ -1733,25 +1021,26 @@ class SSHConnection(): i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def GetAllUEDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - self.command('adb devices', '\$', 15) - self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",str(self.ssh.before)) - self.close() + SSH.command('adb devices', '\$', 15) + #self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) + self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) + SSH.close() else: if (os.path.isfile('./phones_list.txt')): os.remove('./phones_list.txt') - self.command('ls /etc/*/phones*.txt', '\$', 5) - result = re.search('/etc/ci/phones_list.txt', str(self.ssh.before)) - self.close() + SSH.command('ls /etc/*/phones*.txt', '\$', 5) + result = re.search('/etc/ci/phones_list.txt', SSH.getBefore()) + SSH.close() if (result is not None) and (len(self.UEDevices) == 0): - self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') if (os.path.isfile('./phones_list.txt')): phone_list_file = open('./phones_list.txt', 'r') for line in phone_list_file.readlines(): @@ -1768,46 +1057,47 @@ class SSHConnection(): self.UEDevicesRebootCmd.append(comma_split[5]) phone_list_file.close() - if terminate_ue_flag == False: + if terminate_ue_flag == True: if len(self.UEDevices) == 0: logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') sys.exit(1) if len(self.UEDevicesStatus) == 0: cnt = 0 while cnt < len(self.UEDevices): - self.UEDevicesStatus.append(UE_STATUS_DETACHED) + self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) cnt += 1 def GetAllCatMDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - self.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) - self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",str(self.ssh.before)) + SSH.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) + #self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) + self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) else: if (os.path.isfile('./modules_list.txt')): os.remove('./modules_list.txt') - self.command('ls /etc/*/modules*.txt', '\$', 5) - result = re.search('/etc/ci/modules_list.txt', str(self.ssh.before)) - self.close() + SSH.command('ls /etc/*/modules*.txt', '\$', 5) + result = re.search('/etc/ci/modules_list.txt', SSH.getBefore()) + SSH.close() if result is not None: logging.debug('Found a module list file on ADB server') - if terminate_ue_flag == False: + if terminate_ue_flag == True: if len(self.CatMDevices) == 0: logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') sys.exit(1) - self.close() + SSH.close() def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) - result = re.search('mServiceState=(?P[0-9]+)', str(self.ssh.before)) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) + result = re.search('mServiceState=(?P[0-9]+)', SSH.getBefore()) serviceState = 'Service State: UNKNOWN' if result is not None: lServiceState = int(result.group('serviceState')) @@ -1819,7 +1109,7 @@ class SSHConnection(): serviceState = 'Service State: IN_SERVICE' if lServiceState == 2: serviceState = 'Service State: EMERGENCY_ONLY' - result = re.search('mDataConnectionState=(?P[0-9]+)', str(self.ssh.before)) + result = re.search('mDataConnectionState=(?P[0-9]+)', SSH.getBefore()) dataConnectionState = 'Data State: UNKNOWN' if result is not None: lDataConnectionState = int(result.group('dataConnectionState')) @@ -1831,7 +1121,7 @@ class SSHConnection(): dataConnectionState = 'Data State: CONNECTED' if lDataConnectionState == 3: dataConnectionState = 'Data State: SUSPENDED' - result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', str(self.ssh.before)) + result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', SSH.getBefore()) dataConnectionReason = 'Data Reason: UNKNOWN' if result is not None: dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') @@ -1845,20 +1135,20 @@ class SSHConnection(): qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason statusQueue.put(qMsg) lock.release() - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def CheckStatusUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] lock = Lock() @@ -1872,12 +1162,12 @@ class SSHConnection(): i += 1 for job in multi_jobs: job.join() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd /opt/flexran_rtc', '\$', 5) - self.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) - self.command('cat log/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]+)', str(self.ssh.before)) + if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + 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) + result = re.search('Nb Connected UE = (?P[0-9]+)', SSH.getBefore()) passStatus = True if result is not None: nb_ues = int(result.group('nb_ues')) @@ -1888,13 +1178,13 @@ class SSHConnection(): passStatus = False else: htmlOptions = 'N/A' - self.close() + SSH.close() else: passStatus = True htmlOptions = 'N/A' if (status_queue.empty()): - self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(htmlOptions, 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: check_status = True @@ -1908,24 +1198,24 @@ class SSHConnection(): html_cell = '
UE (' + device_id + ')\n' + message + '
' html_queue.put(html_cell) if check_status and passStatus: - self.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def GetAllUEIPAddresses(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') ue_ip_status = 0 self.UEIPAddresses = [] if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('ifconfig oaitun_ue1', '\$', 4) - result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', str(self.ssh.before)) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('ifconfig oaitun_ue1', '\$', 4) + result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', SSH.getBefore()) if result is not None: if result.group('ueipaddress') is not None: UE_IPAddress = result.group('ueipaddress') @@ -1936,21 +1226,21 @@ class SSHConnection(): else: logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') ue_ip_status -= 1 - self.close() + SSH.close() return ue_ip_status - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) idx = 0 for device_id in self.UEDevices: - if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: + if self.UEDevicesStatus[idx] != CONST.UE_STATUS_ATTACHED: idx += 1 continue count = 0 while count < 4: if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) - result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', str(self.ssh.before)) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) + result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') time.sleep(1) @@ -1969,7 +1259,7 @@ class SSHConnection(): continue self.UEIPAddresses.append(UE_IPAddress) idx += 1 - self.close() + SSH.close() return ue_ip_status def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): @@ -1985,50 +1275,50 @@ class SSHConnection(): # Launch ping on the EPC side (true for ltebox and old open-air-cn) # But for OAI-Rel14-CUPS, we launch from python executor launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): launchFromEpc = False ping_time = re.findall("-c (\d+)",str(self.ping_args)) if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - ping_status = self.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) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.command('cd scripts', '\$', 5) + 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) else: 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 - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cat ' + self.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) if result is None: message = 'Packet Loss Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return packetloss = result.group('packetloss') if float(packetloss) == 100: message = 'Packet Loss is 100%' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) if result is None: message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return rtt_min = result.group('rtt_min') @@ -2062,7 +1352,7 @@ class SSHConnection(): statusQueue.put(UE_IPAddress) statusQueue.put(qMsg) lock.release() - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -2070,41 +1360,41 @@ class SSHConnection(): html_queue = SimpleQueue() html_cell = '
OAI UE ping result\n' + qMsg + '
' html_queue.put(html_cell) - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) def PingNoS1(self): check_eNB = True check_OAI_UE = True pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) if ping_from_eNB is not None: - if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '': - Usage() + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') else: if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') try: if ping_from_eNB is not None: - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets/', '\$', 5) + SSH.open(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword()) + SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets/', '\$', 5) else: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) ping_time = re.findall("-c (\d+)",str(self.ping_args)) - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with OAI UE crashed due to TIMEOUT!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') self.PingNoS1_wrong_exit(message) return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) if result is None: message = 'Packet Loss Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') @@ -2116,7 +1406,7 @@ class SSHConnection(): logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') self.PingNoS1_wrong_exit(message) return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) if result is None: message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') @@ -2144,33 +1434,33 @@ class SSHConnection(): elif float(packetloss) > 0: qMsg += '\nPacket Loss is not 0%' logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - self.close() + SSH.close() html_queue = SimpleQueue() ip_addr = 'TBD' html_cell = '
OAI UE ping result\n' + qMsg + '
' html_queue.put(html_cell) if packetLossOK: - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) # copying on the EPC server for logCollection if ping_from_eNB is not None: - copyin_res = self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') else: - copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '.log', EPC.GetSourceCodePath() + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) def Ping(self): - result = re.search('noS1', str(self.Initialize_eNB_args)) + result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) if result is not None: self.PingNoS1() return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): @@ -2179,12 +1469,12 @@ class SSHConnection(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() return multi_jobs = [] @@ -2202,7 +1492,7 @@ class SSHConnection(): job.join() if (status_queue.empty()): - self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: ping_status = True @@ -2217,9 +1507,9 @@ class SSHConnection(): html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (ping_status): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def Iperf_ComputeTime(self): @@ -2255,8 +1545,8 @@ class SSHConnection(): return result def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - self.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', str(self.ssh.before)) + SSH.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', SSH.getBefore()) if result is not None: avgbitrate = result.group('average') maxbitrate = result.group('maximum') @@ -2285,9 +1575,9 @@ class SSHConnection(): if result is None: return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options) - result = re.search('Server Report:', str(self.ssh.before)) + result = re.search('Server Report:', SSH.getBefore()) if result is None: - result = re.search('read failed: Connection refused', str(self.ssh.before)) + result = re.search('read failed: Connection refused', SSH.getBefore()) if result is not None: logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') else: @@ -2311,7 +1601,7 @@ class SSHConnection(): req_bandwidth = '%.1f Gbits/sec' % req_bw req_bw = req_bw * 1000000000 - result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', str(self.ssh.before)) + result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', SSH.getBefore()) if result is not None: bitrate = result.group('bitrate') packetloss = result.group('packetloss') @@ -2462,9 +1752,9 @@ class SSHConnection(): def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', str(self.ssh.before)) + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', SSH.getBefore()) if result is None: - result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', str(self.ssh.before)) + result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', SSH.getBefore()) lock.acquire() statusQueue.put(-1) statusQueue.put(device_id) @@ -2513,7 +1803,7 @@ class SSHConnection(): # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): launchFromEpc = False cmd = 'hostname -I' ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') @@ -2521,14 +1811,14 @@ class SSHConnection(): EPC_Iperf_UE_IPAddress = ret.stdout.strip() port = 5001 + idx if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if udpIperf: - self.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) else: - self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) - self.close() + SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) + SSH.close() else: if self.ueIperfVersion == self.dummyIperfVersion: prefix = '' @@ -2546,11 +1836,11 @@ class SSHConnection(): # Launch iperf client on UE if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2561,50 +1851,50 @@ class SSHConnection(): modified_options = modified_options.replace('-R','') time.sleep(0.5) - self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if (device_id == 'OAI-UE'): - iperf_status = self.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + iperf_status = SSH.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) else: if self.ADBCentralized: - iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + iperf_status = SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) else: - iperf_status = self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - self.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + iperf_status = SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + SSH.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT Case if iperf_status < 0: - self.close() + SSH.close() message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - self.close() + SSH.close() # Kill iperf server on EPC side if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('killall --signal SIGKILL iperf', self.EPCUserName, 5) - self.close() + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('killall --signal SIGKILL iperf', EPC.GetUserName(), 5) + SSH.close() else: cmd = 'killall --signal SIGKILL iperf' logging.debug(cmd) subprocess.run(cmd, shell=True) time.sleep(1) - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') # in case of failure, retrieve server log if (clientStatus == -1) or (clientStatus == -2): if launchFromEpc: 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') - self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath() + '/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 if (device_id == 'OAI-UE'): - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: @@ -2616,48 +1906,48 @@ class SSHConnection(): self.ueIperfVersion = '2.0.5' if (device_id != 'OAI-UE'): - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - self.command('if [ ! -d ' + self.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + EPC.GetSourceCodePath() + '/scripts ; fi', '\$', 5) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) # Checking if iperf / iperf3 are installed if self.ADBCentralized: - self.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) + SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) - result = re.search('iperf3', str(self.ssh.before)) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) + result = re.search('iperf3', SSH.getBefore()) if result is None: - result = re.search('iperf', str(self.ssh.before)) + result = re.search('iperf', SSH.getBefore()) if result is None: message = 'Neither iperf nor iperf3 installed on UE!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return else: if self.ADBCentralized: - self.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) + SSH.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) - result = re.search('iperf version 2.0.5', str(self.ssh.before)) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) + result = re.search('iperf version 2.0.5', SSH.getBefore()) if result is not None: self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', str(self.ssh.before)) + result = re.search('iperf version 2.0.10', SSH.getBefore()) if result is not None: self.ueIperfVersion = '2.0.10' else: useIperf3 = True - self.close() + SSH.close() else: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('iperf --version', '\$', 5) - result = re.search('iperf version 2.0.5', str(self.ssh.before)) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('iperf --version', '\$', 5) + result = re.search('iperf version 2.0.5', SSH.getBefore()) if result is not None: self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', str(self.ssh.before)) + result = re.search('iperf version 2.0.10', SSH.getBefore()) if result is not None: self.ueIperfVersion = '2.0.10' - self.close() + SSH.close() # in case of iperf, UL has its own function if (not useIperf3): result = re.search('-R', str(self.iperf_args)) @@ -2667,44 +1957,44 @@ class SSHConnection(): # Launch the IPERF server on the UE side for DL if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) result = re.search('-u', str(self.iperf_args)) if result is None: - self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) udpIperf = False else: - self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) if self.ADBCentralized: if (useIperf3): - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) else: - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) result = re.search('-u', str(self.iperf_args)) if result is None: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) udpIperf = False else: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) else: - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) time.sleep(0.5) - self.close() + SSH.close() # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn # But for OAI-Rel14-CUPS, we launch from python executor launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): launchFromEpc = False if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2715,18 +2005,18 @@ class SSHConnection(): time.sleep(0.5) if launchFromEpc: - self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) else: if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') if (useIperf3): - self.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + SSH.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) clientStatus = 0 self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) else: if launchFromEpc: - iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + iperf_status = SSH.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) else: if self.ueIperfVersion == self.dummyIperfVersion: prefix = '' @@ -2739,46 +2029,46 @@ class SSHConnection(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) iperf_status = ret.returncode - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cat ' + self.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if iperf_status < 0: if launchFromEpc: - self.close() + SSH.close() message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - self.close() + SSH.close() # Kill the IPERF server that runs in background if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('killall iperf', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('killall iperf', '\$', 5) else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) - result = re.search('shell +(?P\d+)', str(self.ssh.before)) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) + result = re.search('shell +(?P\d+)', SSH.getBefore()) if result is not None: pid_iperf = result.group('pid') if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - self.close() + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + SSH.close() # if the client report is absent, try to analyze the server log file if (clientStatus == -1): 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 (device_id == 'OAI-UE'): - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') else: - self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.GetSourceCodePath() + '/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) @@ -2788,29 +2078,29 @@ class SSHConnection(): if (device_id == 'OAI-UE'): if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): if not launchFromEpc: - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') else: - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) def IperfNoS1(self): - if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - Usage() + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = True pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return server_on_enb = re.search('-R', str(self.iperf_args)) if server_on_enb is not None: - iServerIPAddr = self.eNBIPAddress - iServerUser = self.eNBUserName - iServerPasswd = self.eNBPassword + iServerIPAddr = RAN.GeteNBIPAddress() + iServerUser = RAN.GeteNBUserName() + iServerPasswd = RAN.GeteNBPassword() iClientIPAddr = self.UEIPAddress iClientUser = self.UEUserName iClientPasswd = self.UEPassword @@ -2818,29 +2108,29 @@ class SSHConnection(): iServerIPAddr = self.UEIPAddress iServerUser = self.UEUserName iServerPasswd = self.UEPassword - iClientIPAddr = self.eNBIPAddress - iClientUser = self.eNBUserName - iClientPasswd = self.eNBPassword + iClientIPAddr = RAN.GeteNBIPAddress() + iClientUser = RAN.GeteNBUserName() + iClientPasswd = RAN.GeteNBPassword() if self.iperf_options != 'sink': # Starting the iperf server - self.open(iServerIPAddr, iServerUser, iServerPasswd) + SSH.open(iServerIPAddr, iServerUser, iServerPasswd) # args SHALL be "-c client -u any" # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 # -B 10.0.1.1 -u -s -i 1 -fm server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) server_options = server_options.replace('-c','-B') - self.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) - self.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) + SSH.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) + SSH.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) time.sleep(0.5) - self.close() + SSH.close() # Starting the iperf client modified_options = self.Iperf_ComputeModifiedBW(0, 1) modified_options = modified_options.replace('-R','') iperf_time = self.Iperf_ComputeTime() - self.open(iClientIPAddr, iClientUser, iClientPasswd) - self.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) - iperf_status = self.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) + SSH.open(iClientIPAddr, iClientUser, iClientPasswd) + SSH.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) + iperf_status = SSH.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) status_queue = SimpleQueue() lock = Lock() if iperf_status < 0: @@ -2856,28 +2146,29 @@ class SSHConnection(): status_queue.put('Sink Test : no check') else: clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - self.close() + SSH.close() # Stopping the iperf server if self.iperf_options != 'sink': - self.open(iServerIPAddr, iServerUser, iServerPasswd) - self.command('killall --signal SIGKILL iperf', '\$', 5) + SSH.open(iServerIPAddr, iServerUser, iServerPasswd) + SSH.command('killall --signal SIGKILL iperf', '\$', 5) time.sleep(0.5) - self.close() + SSH.close() + if (clientStatus == -1): if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): os.remove('iperf_server_' + self.testCase_id + '.log') - self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) # copying on the EPC server for logCollection if (clientStatus == -1): - copyin_res = self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') - copyin_res = self.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') + copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') iperf_noperf = False if status_queue.empty(): iperf_status = False @@ -2896,20 +2187,20 @@ class SSHConnection(): html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def Iperf(self): - result = re.search('noS1', str(self.Initialize_eNB_args)) + result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) if result is not None: self.IperfNoS1() return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): @@ -2918,12 +2209,13 @@ class SSHConnection(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) + logging.debug('going here') + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() return @@ -2945,7 +2237,7 @@ class SSHConnection(): status_queue = SimpleQueue() for UE_IPAddress in self.UEIPAddresses: device_id = self.UEDevices[i] - p = Process(target = SSH.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) + p = Process(target = self.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2954,7 +2246,7 @@ class SSHConnection(): job.join() if (status_queue.empty()): - self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: iperf_status = True @@ -2972,11 +2264,11 @@ class SSHConnection(): html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def CheckProcessExist(self, check_eNB, check_OAI_UE): @@ -2984,17 +2276,17 @@ class SSHConnection(): status_queue = SimpleQueue() # in noS1 config, no need to check status from EPC # in gNB also currently no need to check - result = re.search('noS1|band78', str(self.Initialize_eNB_args)) + result = re.search('noS1|band78', str(RAN.GetInitialize_eNB_args())) if result is None: - p = Process(target = SSH.CheckHSSProcess, args = (status_queue,)) + p = Process(target = EPC.CheckHSSProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) - p = Process(target = SSH.CheckMMEProcess, args = (status_queue,)) + p = Process(target = EPC.CheckMMEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) - p = Process(target = SSH.CheckSPGWProcess, args = (status_queue,)) + p = Process(target = EPC.CheckSPGWProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -3002,12 +2294,12 @@ class SSHConnection(): if (check_eNB == False) and (check_OAI_UE == False): return 0 if check_eNB: - p = Process(target = SSH.CheckeNBProcess, args = (status_queue,)) + p = Process(target = RAN.CheckeNBProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) if check_OAI_UE: - p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) + p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -3022,15 +2314,15 @@ class SSHConnection(): status = status_queue.get() if (status < 0): result = status - if result == ENB_PROCESS_FAILED: - fileCheck = re.search('enb_', str(self.eNBLogFiles[0])) + if result == CONST.ENB_PROCESS_FAILED: + fileCheck = re.search('enb_', str(RAN.GeteNBLogFile(0))) if fileCheck is not None: - self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFiles[0], '.') - logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFiles[0]) + SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFile(0), '.') + logStatus = RAN.AnalyzeLogFile_eNB(RAN.GeteNBLogFile[0]) if logStatus < 0: result = logStatus - self.eNBLogFiles[0] = '' - if self.flexranCtrlInstalled and self.flexranCtrlStarted: + RAN.SeteNBLogFile('', 0) + if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): self.TerminateFlexranCtrl() return result @@ -3038,7 +2330,7 @@ class SSHConnection(): multi_jobs = [] status_queue = SimpleQueue() if initialize_OAI_UE_flag == False: - p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) + p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -3053,10 +2345,10 @@ class SSHConnection(): status = status_queue.get() if (status < 0): result = status - if result == OAI_UE_PROCESS_FAILED: + if result == CONST.OAI_UE_PROCESS_FAILED: fileCheck = re.search('ue_', str(self.UELogFile)) if fileCheck is not None: - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') logStatus = self.AnalyzeLogFile_UE(self.UELogFile) if logStatus < 0: result = logStatus @@ -3064,379 +2356,18 @@ class SSHConnection(): def CheckOAIUEProcess(self, status_queue): try: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-uesoftmodem | grep -v grep', '\$', 5) - result = re.search(self.air_interface + '-uesoftmodem', str(self.ssh.before)) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + RAN.Getair_interface() + '-uesoftmodem | grep -v grep', '\$', 5) + result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') - status_queue.put(OAI_UE_PROCESS_FAILED) + status_queue.put(CONST.OAI_UE_PROCESS_FAILED) else: - status_queue.put(OAI_UE_PROCESS_OK) - self.close() + status_queue.put(CONST.OAI_UE_PROCESS_OK) + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) - def CheckeNBProcess(self, status_queue): - try: - # At least the instance 0 SHALL be on! - if self.eNBstatuses[0] == 0: - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - elif self.eNBstatuses[0] == 1: - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - elif self.eNBstatuses[0] == 2: - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - else: - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - self.open(lIpAddr, lUserName, lPassWord) - self.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5) - result = re.search(self.air_interface + '-softmodem', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') - status_queue.put(ENB_PROCESS_FAILED) - else: - status_queue.put(ENB_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckHSSProcess(self, status_queue): - try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('oai_hss -j', str(self.ssh.before)) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('hss_sim s6as diam_hss', str(self.ssh.before)) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m HSS Process Not Found! \u001B[0m') - status_queue.put(HSS_PROCESS_FAILED) - else: - status_queue.put(HSS_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckMMEProcess(self, status_queue): - try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('mme -c', str(self.ssh.before)) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('mme', str(self.ssh.before)) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m') - status_queue.put(MME_PROCESS_FAILED) - else: - status_queue.put(MME_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckSPGWProcess(self, status_queue): - try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('spgwu -c ', str(self.ssh.before)) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) - result = re.search('xGw', str(self.ssh.before)) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m') - status_queue.put(SPGW_PROCESS_FAILED) - else: - status_queue.put(SPGW_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AnalyzeLogFile_eNB(self, eNBlogFile): - if (not os.path.isfile('./' + eNBlogFile)): - return -1 - enb_log_file = open('./' + eNBlogFile, 'r') - exitSignalReceived = False - foundAssertion = False - msgAssertion = '' - msgLine = 0 - foundSegFault = False - foundRealTimeIssue = False - rrcSetupComplete = 0 - rrcReleaseRequest = 0 - rrcReconfigRequest = 0 - rrcReconfigComplete = 0 - rrcReestablishRequest = 0 - rrcReestablishComplete = 0 - rrcReestablishReject = 0 - rlcDiscardBuffer = 0 - rachCanceledProcedure = 0 - uciStatMsgCount = 0 - pdcpFailure = 0 - ulschFailure = 0 - ulschOK = 0 - cdrxActivationMessageCount = 0 - dropNotEnoughRBs = 0 - mbmsRequestMsg = 0 - self.htmleNBFailureMsg = '' - isRRU = False - isSlave = False - slaveReceivesFrameResyncCmd = False - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures = 0 - X2HO_outNbProcedures = 0 - for line in enb_log_file.readlines(): - if X2HO_state == X2_HO_REQ_STATE__IDLE: - result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ - result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK - if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: - result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE - if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: - result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ - if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: - result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures += 1 - if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: - result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_outNbProcedures += 1 - - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[int(self.eNB_instance)]) - res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) - if res1 is not None and res2 is not None: - requested_option = int(res1.group('requested_option')) - applied_option = int(res2.group('applied_option')) - if requested_option == applied_option: - self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' - else: - self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' - result = re.search('Exiting OAI softmodem', str(line)) - if result is not None: - exitSignalReceived = True - result = re.search('[Ss]egmentation [Ff]ault', str(line)) - if result is not None and not exitSignalReceived: - foundSegFault = True - result = re.search('[Cc]ore [dD]ump', str(line)) - if result is not None and not exitSignalReceived: - foundSegFault = True - result = re.search('./ran_build/build/lte-softmodem', str(line)) - if result is not None and not exitSignalReceived: - foundSegFault = True - result = re.search('[Aa]ssertion', str(line)) - if result is not None and not exitSignalReceived: - foundAssertion = True - result = re.search('LLL', str(line)) - if result is not None and not exitSignalReceived: - foundRealTimeIssue = True - if foundAssertion and (msgLine < 3): - msgLine += 1 - msgAssertion += str(line) - result = re.search('Setting function for RU', str(line)) - if result is not None: - isRRU = True - if isRRU: - result = re.search('RU 0 is_slave=yes', str(line)) - if result is not None: - isSlave = True - if isSlave: - result = re.search('Received RRU_frame_resynch command', str(line)) - if result is not None: - slaveReceivesFrameResyncCmd = True - result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) - if result is not None: - rrcSetupComplete += 1 - result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) - if result is not None: - rrcReleaseRequest += 1 - result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) - if result is not None: - rrcReconfigRequest += 1 - result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) - if result is not None: - rrcReconfigComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) - if result is not None: - rrcReestablishRequest += 1 - result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) - if result is not None: - rrcReestablishComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) - if result is not None: - rrcReestablishReject += 1 - result = re.search('CDRX configuration activated after RRC Connection', str(line)) - if result is not None: - cdrxActivationMessageCount += 1 - result = re.search('uci->stat', str(line)) - if result is not None: - uciStatMsgCount += 1 - result = re.search('PDCP.*Out of Resources.*reason', str(line)) - if result is not None: - pdcpFailure += 1 - result = re.search('ULSCH in error in round', str(line)) - if result is not None: - ulschFailure += 1 - if self.air_interface == 'nr': - result = re.search('ULSCH received ok', str(line)) - if result is not None: - ulschOK += 1 - result = re.search('BAD all_segments_received', str(line)) - if result is not None: - rlcDiscardBuffer += 1 - result = re.search('Canceled RA procedure for UE rnti', str(line)) - if result is not None: - rachCanceledProcedure += 1 - result = re.search('dropping, not enough RBs', str(line)) - if result is not None: - dropNotEnoughRBs += 1 - if self.eNBmbmsEnables[int(self.eNB_instance)]: - result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line)) - if result is not None: - mbmsRequestMsg += 1 - enb_log_file.close() - logging.debug(' File analysis completed') - self.htmleNBFailureMsg = '' - if self.air_interface == 'lte': - nodeB_prefix = 'e' - else: - nodeB_prefix = 'g' - if uciStatMsgCount > 0: - statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if pdcpFailure > 0: - statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if ulschFailure > 0: - statMsg = nodeB_prefix + 'NB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if self.air_interface == 'nr': - if ulschOK > 0: - statMsg = nodeB_prefix + 'NB showed ' + str(ulschOK) + ' "ULSCH received ok" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if dropNotEnoughRBs > 0: - statMsg = 'eNB showed ' + str(dropNotEnoughRBs) + ' "dropping, not enough RBs" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if rrcSetupComplete > 0: - rrcMsg = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' RRC Connection Setup(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReleaseRequest > 0: - rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: - rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: - rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if self.eNBmbmsEnables[int(self.eNB_instance)]: - if mbmsRequestMsg > 0: - rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_inNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_outNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) - if res1 is not None: - if cdrxActivationMessageCount > 0: - rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - else: - rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' - logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rachCanceledProcedure > 0: - rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' - logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rachMsg + '\n' - if isRRU: - if isSlave: - if slaveReceivesFrameResyncCmd: - rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - else: - rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - self.prematureExit = True - return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED - if foundSegFault: - logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m') - return ENB_PROCESS_SEG_FAULT - if foundAssertion: - logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m') - self.htmleNBFailureMsg += msgAssertion - return ENB_PROCESS_ASSERTION - if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') - self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE - if rlcDiscardBuffer > 0: - rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' - logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rlcMsg + '\n' - return ENB_PROCESS_REALTIME_ISSUE - return 0 def AnalyzeLogFile_UE(self, UElogFile): if (not os.path.isfile('./' + UElogFile)): @@ -3464,7 +2395,7 @@ class SSHConnection(): nrFoundDCI = 0 nrCRCOK = 0 mbms_messages = 0 - self.htmlUEFailureMsg = '' + HTML.SethtmlUEFailureMsg('') for line in ue_log_file.readlines(): result = re.search('nr_synchro_time', str(line)) if result is not None: @@ -3525,7 +2456,7 @@ class SSHConnection(): result = re.search('No cell synchronization found, abandoning', str(line)) if result is not None: no_cell_sync_found = True - if self.eNBmbmsEnables[0]: + if RAN.GeteNBmbmsEnable(0): result = re.search('TRIED TO PUSH MBMS DATA', str(line)) if result is not None: mbms_messages += 1 @@ -3533,22 +2464,22 @@ class SSHConnection(): if result is not None and (not mib_found): try: mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " nidcell = " + result.group('nidcell') - self.htmlUEFailureMsg += mibMsg + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg) logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " n_rb_dl = " + result.group('n_rb_dl') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " phich_duration = " + result.group('phich_duration') - self.htmlUEFailureMsg += mibMsg + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg) logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " phich_resource = " + result.group('phich_resource') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " tx_ant = " + result.group('tx_ant') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') mib_found = True except Exception as e: @@ -3557,7 +2488,7 @@ class SSHConnection(): if result is not None and (not frequency_found): try: mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') frequency_found = True except Exception as e: @@ -3566,7 +2497,7 @@ class SSHConnection(): if result is not None and (not plmn_found): try: mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') plmn_found = True except Exception as e: @@ -3575,7 +2506,7 @@ class SSHConnection(): if result is not None: try: mibMsg = "The operator is: " + result.group('operator') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') except Exception as e: logging.error('\033[91m' + "Operator name not found" + '\033[0m') @@ -3583,7 +2514,7 @@ class SSHConnection(): if result is not None: try: mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) - self.htmlUEFailureMsg += mibMsg + ' -> ' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + ' -> ') logging.debug('\033[94m' + mibMsg + '\033[0m') except Exception as e: logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') @@ -3593,7 +2524,7 @@ class SSHConnection(): freq = result.group('carrier_frequency') new_freq = re.sub('/[0-9]+','',freq) float_freq = float(new_freq) / 1000000 - self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' + HTMLSethtmlUEFailureMsg(HTMLGethtmlUEFailureMsg() + 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz') logging.debug('\033[94m' + " DL Carrier Frequency is: " + freq + '\033[0m') except Exception as e: logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') @@ -3601,7 +2532,7 @@ class SSHConnection(): if result is not None: try: prb = result.group('allowed_bandwidth') - self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + ' -- PRB: ' + prb + '\n') logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') except Exception as e: logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') @@ -3609,339 +2540,167 @@ class SSHConnection(): if rrcConnectionRecfgComplete > 0: statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' logging.debug('\033[94m' + statMsg + '\033[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if nrUEFlag: if nrDecodeMib > 0: statMsg = 'UE showed ' + str(nrDecodeMib) + ' MIB decode message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if nrFoundDCI > 0: statMsg = 'UE showed ' + str(nrFoundDCI) + ' DCI found message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if nrCRCOK > 0: statMsg = 'UE showed ' + str(nrCRCOK) + ' PDSCH decoding message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if not frequency_found: statMsg = 'NR-UE could NOT synch!' logging.error('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if uciStatMsgCount > 0: statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if pdcpDataReqFailedCount > 0: statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if badDciCount > 0: statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1(A)" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if f1aRetransmissionCount > 0: statMsg = 'UE showed ' + str(f1aRetransmissionCount) + ' "Format1A Retransmission but TBS are different" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if fatalErrorCount > 0: statMsg = 'UE showed ' + str(fatalErrorCount) + ' "FATAL ERROR:" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if macBsrTimerExpiredCount > 0: statMsg = 'UE showed ' + str(fatalErrorCount) + ' "MAC BSR Triggered ReTxBSR Timer expiry" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if self.eNBmbmsEnables[0]: + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + if RAN.GeteNBmbmsEnable(0): if mbms_messages > 0: statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') else: statMsg = 'UE did NOT SHOW "TRIED TO PUSH MBMS DATA" message(s)' logging.debug('\u001B[1;30;41m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if foundSegFault: logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') if not nrUEFlag: - return OAI_UE_PROCESS_SEG_FAULT + return CONST.OAI_UE_PROCESS_SEG_FAULT else: if not frequency_found: - return OAI_UE_PROCESS_SEG_FAULT + return CONST.OAI_UE_PROCESS_SEG_FAULT if foundAssertion: logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') - self.htmlUEFailureMsg += 'UE showed an assertion!\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE showed an assertion!\n') if not nrUEFlag: if not mib_found or not frequency_found: - return OAI_UE_PROCESS_ASSERTION + return CONST.OAI_UE_PROCESS_ASSERTION else: if not frequency_found: - return OAI_UE_PROCESS_ASSERTION + return CONST.OAI_UE_PROCESS_ASSERTION if foundRealTimeIssue: logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') - self.htmlUEFailureMsg += 'UE faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE faced real time issues!\n') + #return CONST.ENB_PROCESS_REALTIME_ISSUE if nrUEFlag: if not frequency_found: - return OAI_UE_PROCESS_COULD_NOT_SYNC + return CONST.OAI_UE_PROCESS_COULD_NOT_SYNC else: if no_cell_sync_found and not mib_found: logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') - self.htmlUEFailureMsg += 'UE could not synchronize!\n' - return OAI_UE_PROCESS_COULD_NOT_SYNC + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE could not synchronize!\n') + return CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return 0 - def TerminateeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) - if self.air_interface == 'lte': - nodeB_prefix = 'e' - else: - nodeB_prefix = 'g' - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5) - time.sleep(10) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5) - time.sleep(5) - self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.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: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - time.sleep(1) - if self.EPC_PcapFileName != '': - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') - self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') - self.close() - logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) - enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] - raw_record_file = enbLogFile.replace('.log', '_record.raw') - replay_log_file = enbLogFile.replace('.log', '_replay.log') - extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') - extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') - self.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) - self.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) - self.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) - self.close() - self.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) - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.eNBLogFiles[int(self.eNB_instance)] = '' - else: - analyzeFile = False - if self.eNBLogFiles[int(self.eNB_instance)] != '': - analyzeFile = True - fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] - self.eNBLogFiles[int(self.eNB_instance)] = '' - if analyzeFile: - copyin_res = self.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') - self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) - self.eNBmbmsEnables[int(self.eNB_instance)] = False - return - if self.eNB_serverId != '0': - self.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) - if (logStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', logStatus) - self.preamtureExit = True - self.eNBmbmsEnables[int(self.eNB_instance)] = False - return - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.eNBmbmsEnables[int(self.eNB_instance)] = False - self.eNBstatuses[int(self.eNB_instance)] = -1 - - def TerminateHSS(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('oai_hss -j', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) - time.sleep(1) - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) - else: - logging.error('This should not happen!') - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateMME(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) - result = re.search('mme -c', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5) - else: - logging.error('This should not happen!') - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateSPGW(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('spgwc -c |spgwu -c ', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) - self.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) - result = re.search('-w ', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5) - else: - logging.error('This should not happen!') - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateFlexranCtrl(self): - if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: + if RAN.GetflexranCtrlInstalled() == False or RAN.GetflexranCtrlStarted() == False: return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) time.sleep(1) - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) time.sleep(1) - self.close() - self.flexranCtrlStarted = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + SSH.close() + RAN.SetflexranCtrlStarted(False) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # back in airplane mode on (ie radio off) if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) - result = re.search('shell +(?P\d+)', str(self.ssh.before)) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) + result = re.search('shell +(?P\d+)', SSH.getBefore()) if result is not None: pid_iperf = result.group('pid') if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - self.close() + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def TerminateUE(self): - terminate_ue_flag = True + terminate_ue_flag = False self.GetAllUEDevices(terminate_ue_flag) multi_jobs = [] i = 0 for device_id in self.UEDevices: - p = Process(target= SSH.TerminateUE_common, args = (device_id,i,)) + p = Process(target= self.TerminateUE_common, args = (device_id,i,)) p.daemon = True p.start() multi_jobs.append(p) i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateOAIUE(self): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-uesoftmodem', str(self.ssh.before)) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-uesoftmodem', SSH.getBefore()) if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT -r .*-uesoftmodem || true', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT -r .*-uesoftmodem || true', '\$', 5) time.sleep(10) - self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-uesoftmodem', str(self.ssh.before)) + SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-uesoftmodem', SSH.getBefore()) if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL -r .*-uesoftmodem || true', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL -r .*-uesoftmodem || true', '\$', 5) time.sleep(5) - self.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.close() + SSH.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.close() result = re.search('ue_', str(self.UELogFile)) if result is not None: - copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') - self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') + HTML.SethtmlUEFailureMsg('Could not copy UE logfile to analyze it!') + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') self.UELogFile = '' return logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') @@ -3953,56 +2712,64 @@ class SSHConnection(): ueAction = 'Connection' if (logStatus < 0): logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') - if self.air_interface == 'lte': + HTML.SethtmlUEFailureMsg('' + ueAction + ' Failed\n' + HTML.GethtmlUEFailureMsg()) + HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') + if RAN.Getair_interface() == 'lte': # In case of sniffing on commercial eNBs we have random results # Not an error then - if (logStatus != OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): + if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): self.Initialize_OAI_UE_args = '' self.AutoTerminateUEandeNB() else: - if (logStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): + if (logStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC): self.Initialize_OAI_UE_args = '' self.AutoTerminateUEandeNB() else: logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.SethtmlUEFailureMsg('' + ueAction + ' Completed\n' + HTML.GethtmlUEFailureMsg()) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.UELogFile = '' else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def AutoTerminateUEandeNB(self): if (self.ADBIPAddress != 'none'): self.testCase_id = 'AUTO-KILL-UE' + HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of UE' + HTML.Setdesc('Automatic Termination of UE') self.ShowTestID() self.TerminateUE() if (self.Initialize_OAI_UE_args != ''): - self.testCase_id = 'AUTO-KILL-UE' - self.desc = 'Automatic Termination of UE' + self.testCase_id = 'AUTO-KILL-OAI-UE' + HTML.SettestCase_id(self.testCase_id) + self.desc = 'Automatic Termination of OAI-UE' + HTML.Setdesc('Automatic Termination of OAI-UE') self.ShowTestID() self.TerminateOAIUE() - if (self.Initialize_eNB_args != ''): + if (RAN.GetInitialize_eNB_args() != ''): self.testCase_id = 'AUTO-KILL-eNB' + HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of eNB' + HTML.Setdesc('Automatic Termination of eNB') self.ShowTestID() - self.eNB_instance = '0' - self.TerminateeNB() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: + RAN.SeteNB_instance('0') + RAN.TerminateeNB() + if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): self.testCase_id = 'AUTO-KILL-flexran-ctl' + HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of FlexRan CTL' + HTML.Setdesc('Automatic Termination of FlexRan CTL') self.ShowTestID() self.TerminateFlexranCtrl() - self.prematureExit = True + RAN.SetprematureExit(True) def IdleSleep(self): time.sleep(self.idle_sleep_time) - self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', CONST.ALL_PROCESSES_OK) def X2_Status(self, idx, fileName): - cmd = "curl --silent http://" + self.EPCIPAddress + ":9999/stats | jq '.' > " + fileName + cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName message = cmd + '\n' logging.debug(cmd) subprocess.run(cmd, shell=True) @@ -4051,7 +2818,7 @@ class SSHConnection(): logging.debug(msg) fullMessage += msg + '\n' if self.x2_ho_options == 'network': - if self.flexranCtrlInstalled and self.flexranCtrlStarted: + if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): self.x2ENBBsIds = [] self.x2ENBConnectedUEs = [] self.x2ENBBsIds.append([]) @@ -4066,7 +2833,7 @@ class SSHConnection(): eNB_cnt = self.x2NbENBs cnt = 0 while cnt < eNB_cnt: - cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" + cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) @@ -4080,7 +2847,7 @@ class SSHConnection(): while cnt < eNB_cnt: ueIdx = 0 while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]): - cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) + cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) @@ -4101,22 +2868,22 @@ class SSHConnection(): logging.debug(msg) fullMessage += msg + '' html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) else: msg = "X2 Handover FAILED" logging.error(msg) fullMessage += msg + '' html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', CONST.ALL_PROCESSES_OK) def LogCollectBuild(self): - if (self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != ''): - IPAddress = self.eNBIPAddress - UserName = self.eNBUserName - Password = self.eNBPassword - SourceCodePath = self.eNBSourceCodePath + if (RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != ''): + IPAddress = RAN.GeteNBIPAddress() + UserName = RAN.GeteNBUserName() + Password = RAN.GeteNBPassword() + SourceCodePath = RAN.GeteNBSourceCodePath() elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): IPAddress = self.UEIPAddress UserName = self.UEUserName @@ -4124,109 +2891,55 @@ class SSHConnection(): SourceCodePath = self.UESourceCodePath else: sys.exit('Insufficient Parameter') - self.open(IPAddress, UserName, Password) - self.command('cd ' + SourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('rm -f build.log.zip', '\$', 5) - self.command('zip build.log.zip build_log_*/*', '\$', 60) - self.close() - - def LogCollecteNB(self): - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) - self.close() - + SSH.open(IPAddress, UserName, Password) + 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.close() def LogCollectPing(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('rm -f ping.log.zip', '\$', 5) - self.command('zip ping.log.zip ping*.log', '\$', 60) - self.command('rm ping*.log', '\$', 5) - self.close() + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('rm -f ping.log.zip', '\$', 5) + SSH.command('zip ping.log.zip ping*.log', '\$', 60) + SSH.command('rm ping*.log', '\$', 5) + SSH.close() def LogCollectIperf(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('rm -f iperf.log.zip', '\$', 5) - self.command('zip iperf.log.zip iperf*.log', '\$', 60) - self.command('rm iperf*.log', '\$', 5) - self.close() - - def LogCollectHSS(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f hss.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip hss.log.zip hss*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm hss*.log', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) - self.command('zip hss.log.zip hss.log', '\$', 60) - else: - logging.error('This option should not occur!') - self.close() - - def LogCollectMME(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f mme.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip mme.log.zip mme*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm mme*.log', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) - self.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) - else: - logging.error('This option should not occur!') - self.close() - - def LogCollectSPGW(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f spgw.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip spgw.log.zip spgw*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm spgw*.log', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) - self.command('zip spgw.log.zip xGwLog.0', '\$', 60) - else: - logging.error('This option should not occur!') - self.close() - + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('rm -f iperf.log.zip', '\$', 5) + SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) + SSH.command('rm iperf*.log', '\$', 5) + SSH.close() + def LogCollectOAIUE(self): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) - self.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) - self.close() + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) + SSH.close() def RetrieveSystemVersion(self, machine): - if self.eNBIPAddress == 'none' or self.UEIPAddress == 'none': - self.OsVersion = 'Ubuntu 16.04.5 LTS' - self.KernelVersion = '4.15.0-45-generic' - self.UhdVersion = '3.13.0.1-0' - self.UsrpBoard = 'B210' - self.CpuNb = '4' - self.CpuModel = 'Intel(R) Core(TM) i5-6200U' - self.CpuMHz = '2399.996 MHz' + if RAN.GeteNBIPAddress() == 'none' or self.UEIPAddress == 'none': + HTML.SetOsVersion('Ubuntu 16.04.5 LTS', 0) + HTML.SetKernelVersion('4.15.0-45-generic', 0) + HTML.SetUhdVersion('3.13.0.1-0', 0) + HTML.SetUsrpBoard('B210', 0) + HTML.SetCpuNb('4', 0) + HTML.SetCpuModel('Intel(R) Core(TM) i5-6200U', 0) + HTML.SetCpuMHz('2399.996 MHz', 0) return 0 if machine == 'eNB': - if self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != '': - IPAddress = self.eNBIPAddress - UserName = self.eNBUserName - Password = self.eNBPassword + if RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != '': + IPAddress = RAN.GeteNBIPAddress() + UserName = RAN.GeteNBUserName() + Password = RAN.GeteNBPassword() + idx = 0 else: return -1 if machine == 'UE': @@ -4234,386 +2947,73 @@ class SSHConnection(): IPAddress = self.UEIPAddress UserName = self.UEUserName Password = self.UEPassword + idx = 1 else: return -1 - self.open(IPAddress, UserName, Password) - self.command('lsb_release -a', '\$', 5) - result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) + SSH.open(IPAddress, UserName, Password) + SSH.command('lsb_release -a', '\$', 5) + result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) if result is not None: - self.OsVersion = result.group('os_type') - logging.debug('OS is: ' + self.OsVersion) + OsVersion = result.group('os_type') + logging.debug('OS is: ' + OsVersion) + HTML.SetOsVersion(OsVersion, idx) else: - self.command('hostnamectl', '\$', 5) - result = re.search('Operating System: (?P[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) + SSH.command('hostnamectl', '\$', 5) + result = re.search('Operating System: (?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) if result is not None: - self.OsVersion = result.group('os_type') - if self.OsVersion == 'CentOS Linux 7 ': - self.command('cat /etc/redhat-release', '\$', 5) - result = re.search('CentOS Linux release (?P[0-9\.]+)', str(self.ssh.before)) + OsVersion = result.group('os_type') + if OsVersion == 'CentOS Linux 7 ': + SSH.command('cat /etc/redhat-release', '\$', 5) + result = re.search('CentOS Linux release (?P[0-9\.]+)', SSH.getBefore()) if result is not None: - self.OsVersion = self.OsVersion.replace('7 ', result.group('os_version')) - logging.debug('OS is: ' + self.OsVersion) - self.command('uname -r', '\$', 5) - result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before)) + OsVersion = OsVersion.replace('7 ', result.group('os_version')) + logging.debug('OS is: ' + OsVersion) + HTML.SetOsVersion(OsVersion, idx) + SSH.command('uname -r', '\$', 5) + result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', SSH.getBefore()) if result is not None: - self.KernelVersion = result.group('kernel_version') - logging.debug('Kernel Version is: ' + self.KernelVersion) - self.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) - result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', str(self.ssh.before)) + KernelVersion = result.group('kernel_version') + logging.debug('Kernel Version is: ' + KernelVersion) + HTML.SetKernelVersion(KernelVersion, idx) + SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) + result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', SSH.getBefore()) if result is not None: - self.UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + self.UhdVersion) + UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + UhdVersion) + HTML.SetUhdVersion(UhdVersion, idx) else: - self.command('uhd_config_info --version', '\$', 5) - result = re.search('UHD (?P[a-zA-Z0-9\.\-]+)', str(self.ssh.before)) + SSH.command('uhd_config_info --version', '\$', 5) + result = re.search('UHD (?P[a-zA-Z0-9\.\-]+)', SSH.getBefore()) if result is not None: - self.UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + self.UhdVersion) - self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 60) - usrp_boards = re.findall('product: ([0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before)) + UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + UhdVersion) + HTML.SetUhdVersion(UhdVersion, idx) + SSH.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 60) + usrp_boards = re.findall('product: ([0-9A-Za-z]+)\\\\r\\\\n', SSH.getBefore()) count = 0 for board in usrp_boards: if count == 0: - self.UsrpBoard = board + UsrpBoard = board else: - self.UsrpBoard += ',' + board + UsrpBoard += ',' + board count += 1 if count > 0: - logging.debug('USRP Board(s) : ' + self.UsrpBoard) - self.command('lscpu', '\$', 5) - result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', str(self.ssh.before)) + logging.debug('USRP Board(s) : ' + UsrpBoard) + HTML.SetUsrpBoard(UsrpBoard, idx) + SSH.command('lscpu', '\$', 5) + result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', SSH.getBefore()) if result is not None: - self.CpuNb = result.group('nb_cpus') - logging.debug('nb_cpus: ' + self.CpuNb) - self.CpuModel = result.group('model') - logging.debug('model: ' + self.CpuModel) - self.CpuMHz = result.group('cpu_mhz') + ' MHz' - logging.debug('cpu_mhz: ' + self.CpuMHz) - self.close() - -#----------------------------------------------------------- -# HTML Reporting.... -#----------------------------------------------------------- - def CreateHtmlHeader(self): - if (not self.htmlHeaderCreated): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML header \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - self.htmlFile = open('test_results.html', 'w') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') - self.htmlFile.write('\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if self.ranAllowMerge != '': - commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True) - commit_message = commit_message.strip() - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranTargetBranch == ''): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + self.ranRepository + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + self.ranBranch + '
Source Commit ID Commit ID ' + self.ranCommitID + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.ranTargetBranch + '
\n') - - if (self.ADBIPAddress != 'none'): - terminate_ue_flag = True - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

' + str(len(self.UEDevices)) + ' UE(s) is(are) connected to ADB bench server

\n') - self.htmlFile.write('

' + str(len(self.CatMDevices)) + ' CAT-M UE(s) is(are) connected to bench server

\n') - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

' + str(len(self.UEDevices)) + ' OAI UE(s) is(are) connected to CI bench

\n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.close() - - def CreateHtmlTabHeader(self): - if (not self.htmlHeaderCreated): - if (not os.path.isfile('test_results.html')): - self.CreateHtmlHeader() - self.htmlFile = open('test_results.html', 'a') - if (self.nbTestXMLfiles == 1): - self.htmlFile.write('
\n') - self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') - else: - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.htmlUEConnected == -1): - terminate_ue_flag = True - if (self.ADBIPAddress != 'none'): - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' \n') - i += 1 - self.htmlFile.write(' \n') - self.htmlHeaderCreated = True - - def CreateHtmlTabFooter(self, passStatus): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') - self.htmlFile.write('
\n') - self.htmlFile.close() - time.sleep(1) - if passStatus: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" - subprocess.run(cmd, shell=True) - else: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" - subprocess.run(cmd, shell=True) - self.htmlFooterCreated = False - - def CreateHtmlFooter(self, passStatus): - if (os.path.isfile('test_results.html')): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML footer \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - - self.htmlFile = open('test_results.html', 'a') - self.htmlFile.write('
\n') - self.htmlFile.write('

\n') - self.htmlFile.write(' \n') - - machines = [ 'eNB', 'UE' ] - for machine in machines: - res = self.RetrieveSystemVersion(machine) - if res == -1: - continue - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
' + str(machine) + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') - self.htmlFile.write('

\n') - self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('\n') - self.htmlFile.close() - - def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - if (processesStatus == 0): - self.htmlFile.write(' ' + str(status) + '\n') - elif (processesStatus == ENB_PROCESS_FAILED): - self.htmlFile.write(' KO - eNB process not found\n') - elif (processesStatus == OAI_UE_PROCESS_FAILED): - self.htmlFile.write(' KO - OAI UE process not found\n') - elif (processesStatus == ENB_PROCESS_SEG_FAULT) or (processesStatus == OAI_UE_PROCESS_SEG_FAULT): - self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') - elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): - self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') - elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): - self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') - elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): - self.htmlFile.write(' OK?\n') - elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): - self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') - elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): - self.htmlFile.write(' KO - UE could not sync\n') - elif (processesStatus == HSS_PROCESS_FAILED): - self.htmlFile.write(' KO - HSS process not found\n') - elif (processesStatus == MME_PROCESS_FAILED): - self.htmlFile.write(' KO - MME process not found\n') - elif (processesStatus == SPGW_PROCESS_FAILED): - self.htmlFile.write(' KO - SPGW process not found\n') - elif (processesStatus == UE_IP_ADDRESS_ISSUE): - self.htmlFile.write(' KO - Could not retrieve UE IP address\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - if (len(str(self.htmleNBFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') - self.htmleNBFailureMsg = '' - elif (len(str(self.htmlUEFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') - self.htmlUEFailureMsg = '' - else: - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') - - def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - addOrangeBK = False - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - self.htmlFile.write(' ' + str(status) + '\n') - else: - addOrangeBK = True - self.htmlFile.write(' ' + str(status) + '\n') - i = 0 - while (i < self.htmlUEConnected): - if (i < ue_status): - if (not ue_queue.empty()): - if (addOrangeBK): - self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') - else: - self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') - else: - self.htmlFile.write(' -\n') - else: - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') + CpuNb = result.group('nb_cpus') + logging.debug('nb_cpus: ' + CpuNb) + HTML.SetCpuNb(CpuNb, idx) + CpuModel = result.group('model') + logging.debug('model: ' + CpuModel) + HTML.SetCpuModel(CpuModel, idx) + CpuMHz = result.group('cpu_mhz') + ' MHz' + logging.debug('cpu_mhz: ' + CpuMHz) + HTML.SetCpuMHz(CpuMHz, idx) + SSH.close() #----------------------------------------------------------- # ShowTestID() @@ -4624,50 +3024,6 @@ class SSHConnection(): logging.debug('\u001B[1m' + self.desc + '\u001B[0m') logging.debug('\u001B[1m----------------------------------------\u001B[0m') -#----------------------------------------------------------- -# Usage() -#----------------------------------------------------------- -def Usage(): - print('----------------------------------------------------------------------------------------------------------------------') - print('main.py Ver:' + Version) - print('----------------------------------------------------------------------------------------------------------------------') - print('Usage: python main.py [options]') - print(' --help Show this help.') - print(' --mode=[Mode]') - print(' TesteNB') - print(' InitiateHtml, FinalizeHtml') - print(' TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW') - print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') - print('---------------------------------------------------------------------------------------------------- Git Options --') - print(' --ranRepository=[OAI RAN Repository URL]') - print(' --ranBranch=[OAI RAN Repository Branch]') - print(' --ranCommitID=[OAI RAN Repository Commit SHA-1]') - print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)]') - print(' --ranTargetBranch=[Target Branch in case of a Merge Request]') - print('--------------------------------------------------------------------------------------------- eNB Server Options --') - print(' --eNBIPAddress=[eNB\'s IP Address]') - print(' --eNBUserName=[eNB\'s Login User Name]') - print(' --eNBPassword=[eNB\'s Login Password]') - print(' --eNBSourceCodePath=[eNB\'s Source Code Path]') - print('------------------------------------------------------------------------------------------ OAI UE Server Options --') - print(' --UEIPAddress=[UE\'s IP Address]') - print(' --UEUserName=[UE\'s Login User Name]') - print(' --UEPassword=[UE\'s Login Password]') - print(' --UESourceCodePath=[UE\'s Source Code Path]') - print('--------------------------------------------------------------------------------------------- EPC Server Options --') - print(' --EPCIPAddress=[EPC\'s IP Address]') - print(' --EPCUserName=[EPC\'s Login User Name]') - print(' --EPCPassword=[EPC\'s Login Password]') - print(' --EPCSourceCodePath=[EPC\'s Source Code Path]') - print(' --EPCType=[EPC\'s Type: OAI or ltebox or OAI-Rel14-CUPS]') - print('--------------------------------------------------------------------------------------------- ABD Server Options --') - print(' --ADBIPAddress=[ADB\'s IP Address]') - print(' --ADBUserName=[ADB\'s Login User Name]') - print(' --ADBPassword=[ADB\'s Login Password]') - print('----------------------------------------------------------------------------------------------------------------------') - print(' --XMLTestFile=[XML Test File to be run]') - print('----------------------------------------------------------------------------------------------------------------------') - def CheckClassValidity(action,id): if action != 'Build_eNB' and action != 'WaitEndBuild_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover': logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) @@ -4676,143 +3032,145 @@ def CheckClassValidity(action,id): def GetParametersFromXML(action): if action == 'Build_eNB': - SSH.Build_eNB_args = test.findtext('Build_eNB_args') + RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') if (forced_workspace_cleanup is None): - SSH.Build_eNB_forced_workspace_cleanup = False + RAN.SetBuild_eNB_forced_workspace_cleanup(False) else: if re.match('true', forced_workspace_cleanup, re.IGNORECASE): - SSH.Build_eNB_forced_workspace_cleanup = True + RAN.SetBuild_eNB_forced_workspace_cleanup(True) else: - SSH.Build_eNB_forced_workspace_cleanup = False - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' + RAN.SetBuild_eNB_forced_workspace_cleanup(False) + RAN.SeteNB_instance(test.findtext('eNB_instance')) + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') xmlBgBuildField = test.findtext('backgroundBuild') if (xmlBgBuildField is None): - SSH.backgroundBuild = False + RAN.SetbackgroundBuild(False) else: if re.match('true', xmlBgBuildField, re.IGNORECASE): - SSH.backgroundBuild = True + RAN.SetbackgroundBuild(True) else: - SSH.backgroundBuild = False + RAN.SetbackgroundBuild(False) if action == 'WaitEndBuild_eNB': - SSH.Build_eNB_args = test.findtext('Build_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' + RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) + RAN.SeteNB_instance(test.findtext('eNB_instance')) + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') if action == 'Initialize_eNB': - SSH.Initialize_eNB_args = test.findtext('Initialize_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - SSH.air_interface = test.findtext('air_interface') - if (SSH.air_interface is None): - SSH.air_interface = 'lte' + RAN.SetInitialize_eNB_args(test.findtext('Initialize_eNB_args')) + RAN.SeteNB_instance(test.findtext('eNB_instance')) + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') + CiTestObj.air_interface = test.findtext('air_interface') + if (CiTestObj.air_interface is None): + CiTestObj.air_interface = 'lte' else: - SSH.air_interface = SSH.air_interface.lower() + CiTestObj.air_interface = CiTestObj.air_interface.lower() + RAN.Setair_interface(CiTestObj.air_interface) if action == 'Terminate_eNB': - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - SSH.air_interface = test.findtext('air_interface') - if (SSH.air_interface is None): - SSH.air_interface = 'lte' + RAN.SeteNB_instance(test.findtext('eNB_instance')) + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') + CiTestObj.air_interface = test.findtext('air_interface') + if (CiTestObj.air_interface is None): + CiTestObj.air_interface = 'lte' else: - SSH.air_interface = SSH.air_interface.lower() + CiTestObj.air_interface = CiTestObj.air_interface.lower() + RAN.Setair_interface(CiTestObj.air_interface) if action == 'Attach_UE': nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') if (nbMaxUEtoAttach is None): - SSH.nbMaxUEtoAttach = -1 + CiTestObj.nbMaxUEtoAttach = -1 else: - SSH.nbMaxUEtoAttach = int(nbMaxUEtoAttach) + CiTestObj.nbMaxUEtoAttach = int(nbMaxUEtoAttach) if action == 'CheckStatusUE': expectedNBUE = test.findtext('expectedNbOfConnectedUEs') if (expectedNBUE is None): - SSH.expectedNbOfConnectedUEs = -1 + CiTestObj.expectedNbOfConnectedUEs = -1 else: - SSH.expectedNbOfConnectedUEs = int(expectedNBUE) + CiTestObj.expectedNbOfConnectedUEs = int(expectedNBUE) if action == 'Build_OAI_UE': - SSH.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') - SSH.clean_repository = test.findtext('clean_repository') - if (SSH.clean_repository == 'false'): - SSH.clean_repository = False + CiTestObj.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') + CiTestObj.clean_repository = test.findtext('clean_repository') + if (CiTestObj.clean_repository == 'false'): + CiTestObj.clean_repository = False else: - SSH.clean_repository = True + CiTestObj.clean_repository = True if action == 'Initialize_OAI_UE': - SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') - SSH.UE_instance = test.findtext('UE_instance') - if (SSH.UE_instance is None): - SSH.UE_instance = '0' - SSH.air_interface = test.findtext('air_interface') - if (SSH.air_interface is None): - SSH.air_interface = 'lte' + CiTestObj.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') + CiTestObj.UE_instance = test.findtext('UE_instance') + if (CiTestObj.UE_instance is None): + CiTestObj.UE_instance = '0' + CiTestObj.air_interface = test.findtext('air_interface') + if (CiTestObj.air_interface is None): + CiTestObj.air_interface = 'lte' else: - SSH.air_interface = SSH.air_interface.lower() + CiTestObj.air_interface = CiTestObj.air_interface.lower() if action == 'Terminate_OAI_UE': - SSH.eNB_instance = test.findtext('UE_instance') - if (SSH.UE_instance is None): - SSH.UE_instance = '0' + RAN.SeteNB_instance(test.findtext('UE_instance')) + if (CiTestObj.UE_instance is None): + CiTestObj.UE_instance = '0' if action == 'Ping' or action == 'Ping_CatM_module': - SSH.ping_args = test.findtext('ping_args') - SSH.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') + CiTestObj.ping_args = test.findtext('ping_args') + CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') if action == 'Iperf': - SSH.iperf_args = test.findtext('iperf_args') - SSH.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') - SSH.iperf_profile = test.findtext('iperf_profile') - if (SSH.iperf_profile is None): - SSH.iperf_profile = 'balanced' + CiTestObj.iperf_args = test.findtext('iperf_args') + CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') + CiTestObj.iperf_profile = test.findtext('iperf_profile') + if (CiTestObj.iperf_profile is None): + CiTestObj.iperf_profile = 'balanced' else: - if SSH.iperf_profile != 'balanced' and SSH.iperf_profile != 'unbalanced' and SSH.iperf_profile != 'single-ue': - logging.debug('ERROR: test-case has wrong profile ' + SSH.iperf_profile) - SSH.iperf_profile = 'balanced' - SSH.iperf_options = test.findtext('iperf_options') - if (SSH.iperf_options is None): - SSH.iperf_options = 'check' + if CiTestObj.iperf_profile != 'balanced' and CiTestObj.iperf_profile != 'unbalanced' and CiTestObj.iperf_profile != 'single-ue': + logging.debug('ERROR: test-case has wrong profile ' + CiTestObj.iperf_profile) + CiTestObj.iperf_profile = 'balanced' + CiTestObj.iperf_options = test.findtext('iperf_options') + if (CiTestObj.iperf_options is None): + CiTestObj.iperf_options = 'check' else: - if SSH.iperf_options != 'check' and SSH.iperf_options != 'sink': - logging.debug('ERROR: test-case has wrong option ' + SSH.iperf_options) - SSH.iperf_options = 'check' + if CiTestObj.iperf_options != 'check' and CiTestObj.iperf_options != 'sink': + logging.debug('ERROR: test-case has wrong option ' + CiTestObj.iperf_options) + CiTestObj.iperf_options = 'check' if action == 'IdleSleep': string_field = test.findtext('idle_sleep_time_in_sec') if (string_field is None): - SSH.idle_sleep_time = 5 + CiTestObj.idle_sleep_time = 5 else: - SSH.idle_sleep_time = int(string_field) + CiTestObj.idle_sleep_time = int(string_field) if action == 'Perform_X2_Handover': string_field = test.findtext('x2_ho_options') if (string_field is None): - SSH.x2_ho_options = 'network' + CiTestObj.x2_ho_options = 'network' else: if string_field != 'network': logging.error('ERROR: test-case has wrong option ' + string_field) - SSH.x2_ho_options = 'network' + CiTestObj.x2_ho_options = 'network' else: - SSH.x2_ho_options = string_field + CiTestObj.x2_ho_options = string_field #check if given test is in list @@ -4831,7 +3189,23 @@ def receive_signal(signum, frame): # Parameter Check #----------------------------------------------------------- mode = '' -SSH = SSHConnection() +CiTestObj = OaiCiTest() + +import sshconnection +import epc +import helpreadme as HELP +import ran +import html +import constants + +SSH = sshconnection.SSHConnection() +EPC = epc.EPCManagement() +RAN = ran.RANManagement() +HTML = html.HTMLManagement() + +EPC.SetHtmlObj(HTML) +RAN.SetHtmlObj(HTML) +RAN.SetEpcObj(EPC) argvs = sys.argv argc = len(argvs) @@ -4839,8 +3213,9 @@ cwd = os.getcwd() while len(argvs) > 1: myArgv = argvs.pop(1) # 0th is this file's name + if re.match('^\-\-help$', myArgv, re.IGNORECASE): - Usage() + HELP.GenericHelp(CONST.Version) sys.exit(0) elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) @@ -4850,7 +3225,9 @@ while len(argvs) > 1: matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) - SSH.ranRepository = matchReg.group(1) + CiTestObj.ranRepository = matchReg.group(1) + RAN.SetranRepository(matchReg.group(1)) + HTML.SetranRepository(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) @@ -4858,259 +3235,286 @@ while len(argvs) > 1: matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) doMerge = matchReg.group(1) if ((doMerge == 'true') or (doMerge == 'True')): - SSH.ranAllowMerge = True + CiTestObj.ranAllowMerge = True + RAN.SetranAllowMerge(True) + HTML.SetranAllowMerge(True) elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) - SSH.ranBranch = matchReg.group(1) + CiTestObj.ranBranch = matchReg.group(1) + RAN.SetranBranch(matchReg.group(1)) + HTML.SetranBranch(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) else: matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) - SSH.ranCommitID = matchReg.group(1) + CiTestObj.ranCommitID = matchReg.group(1) + RAN.SetranCommitID(matchReg.group(1)) + HTML.SetranCommitID(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) else: matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) - SSH.ranTargetBranch = matchReg.group(1) + CiTestObj.ranTargetBranch = matchReg.group(1) + RAN.SetranTargetBranch(matchReg.group(1)) + HTML.SetranTargetBranch(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) - SSH.eNBIPAddress = matchReg.group(1) + RAN.SeteNBIPAddress(matchReg.group(1)) elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1IPAddress = matchReg.group(1) + RAN.SeteNB1IPAddress(matchReg.group(1)) elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2IPAddress = matchReg.group(1) + RAN.SeteNB2IPAddress(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) - SSH.eNBUserName = matchReg.group(1) + RAN.SeteNBUserName(matchReg.group(1)) elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1UserName = matchReg.group(1) + RAN.SeteNB1UserName(matchReg.group(1)) elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2UserName = matchReg.group(1) + RAN.SeteNB2UserName(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) - SSH.eNBPassword = matchReg.group(1) + RAN.SeteNBPassword(matchReg.group(1)) elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1Password = matchReg.group(1) + RAN.SeteNB1Password(matchReg.group(1)) elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2Password = matchReg.group(1) + RAN.SeteNB2Password(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) - SSH.eNBSourceCodePath = matchReg.group(1) + RAN.SeteNBSourceCodePath(matchReg.group(1)) elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1SourceCodePath = matchReg.group(1) + RAN.SeteNB1SourceCodePath(matchReg.group(1)) elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2SourceCodePath = matchReg.group(1) + RAN.SeteNB2SourceCodePath(matchReg.group(1)) elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCIPAddress = matchReg.group(1) - elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCBranch = matchReg.group(1) + EPC.SetIPAddress(matchReg.group(1)) elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCUserName = matchReg.group(1) + EPC.SetUserName(matchReg.group(1)) elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCPassword = matchReg.group(1) + EPC.SetPassword(matchReg.group(1)) elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCSourceCodePath = matchReg.group(1) + EPC.SetSourceCodePath(matchReg.group(1)) elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): - SSH.EPCType = matchReg.group(1) + EPC.SetType(matchReg.group(1)) else: sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBIPAddress = matchReg.group(1) + CiTestObj.ADBIPAddress = matchReg.group(1) elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBUserName = matchReg.group(1) + CiTestObj.ADBUserName = matchReg.group(1) elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): if re.match('distributed', matchReg.group(1), re.IGNORECASE): - SSH.ADBCentralized = False + CiTestObj.ADBCentralized = False else: - SSH.ADBCentralized = True + CiTestObj.ADBCentralized = True else: sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBPassword = matchReg.group(1) + CiTestObj.ADBPassword = matchReg.group(1) elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) - SSH.testXMLfiles.append(matchReg.group(1)) - SSH.nbTestXMLfiles += 1 + CiTestObj.testXMLfiles.append(matchReg.group(1)) + HTML.SettestXMLfiles(matchReg.group(1)) + HTML.SetnbTestXMLfiles(HTML.GetnbTestXMLfiles()+1) elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.UEIPAddress = matchReg.group(1) + CiTestObj.UEIPAddress = matchReg.group(1) elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.UEUserName = matchReg.group(1) + CiTestObj.UEUserName = matchReg.group(1) elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.UEPassword = matchReg.group(1) + CiTestObj.UEPassword = matchReg.group(1) elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.UESourceCodePath = matchReg.group(1) + CiTestObj.UESourceCodePath = matchReg.group(1) elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) finalStatus = matchReg.group(1) if ((finalStatus == 'true') or (finalStatus == 'True')): - SSH.finalStatus = True + CiTestObj.finalStatus = True else: - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Invalid Parameter: ' + myArgv) if re.match('^TerminateeNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '': - Usage() + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.eNB_serverId = '0' - SSH.eNB_instance = '0' - SSH.eNBSourceCodePath = '/tmp/' - SSH.TerminateeNB() + RAN.SeteNB_serverId('0') + RAN.SeteNB_instance('0') + RAN.SeteNBSourceCodePath('/tmp/') + RAN.TerminateeNB() elif re.match('^TerminateUE$', mode, re.IGNORECASE): - if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): - Usage() + if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) - SSH.TerminateUE() + CiTestObj.TerminateUE() elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): - if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '': - Usage() + if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) - SSH.TerminateOAIUE() + CiTestObj.TerminateOAIUE() elif re.match('^TerminateHSS$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.TerminateHSS() + EPC.TerminateHSS() elif re.match('^TerminateMME$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.TerminateMME() + EPC.TerminateMME() elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.TerminateSPGW() + EPC.TerminateSPGW() elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): - if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == ''): - Usage() + if (RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.LogCollectBuild() + CiTestObj.LogCollectBuild() elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '': - Usage() + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.LogCollecteNB() + RAN.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.LogCollectHSS() + EPC.LogCollectHSS() elif re.match('^LogCollectMME$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.LogCollectMME() + EPC.LogCollectMME() elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.LogCollectSPGW() + EPC.LogCollectSPGW() elif re.match('^LogCollectPing$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.LogCollectPing() + CiTestObj.LogCollectPing() elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.LogCollectIperf() + CiTestObj.LogCollectIperf() elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): - if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': - Usage() + if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.LogCollectOAIUE() + CiTestObj.LogCollectOAIUE() elif re.match('^InitiateHtml$', mode, re.IGNORECASE): - if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): - Usage() + if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') count = 0 foundCount = 0 - while (count < SSH.nbTestXMLfiles): - xml_test_file = cwd + "/" + SSH.testXMLfiles[count] + while (count < HTML.GetnbTestXMLfiles()): + #xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[count] + xml_test_file = sys.path[0] + "/" + CiTestObj.testXMLfiles[count] if (os.path.isfile(xml_test_file)): try: xmlTree = ET.parse(xml_test_file) except: print("Error while parsing file: " + xml_test_file) xmlRoot = xmlTree.getroot() - SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) - SSH.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='test-tab-' + str(count))) + HTML.SethtmlTabIcons(xmlRoot.findtext('htmlTabIcon',default='info-sign')) foundCount += 1 count += 1 - if foundCount != SSH.nbTestXMLfiles: - SSH.nbTestXMLfiles = foundCount - SSH.CreateHtmlHeader() + if foundCount != HTML.GetnbTestXMLfiles(): + HTML.SetnbTestXMLfiles(foundcount) + + if (CiTestObj.ADBIPAddress != 'none'): + terminate_ue_flag = False + CiTestObj.GetAllUEDevices(terminate_ue_flag) + CiTestObj.GetAllCatMDevices(terminate_ue_flag) + HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) + HTML.SethtmlNb_Smartphones(len(CiTestObj.UEDevices)) + HTML.SethtmlNb_CATM_Modules(len(CiTestObj.CatMDevices)) + HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress) elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): - SSH.CreateHtmlFooter(SSH.finalStatus) + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML footer \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + + CiTestObj.RetrieveSystemVersion('eNB') + CiTestObj.RetrieveSystemVersion('UE') + HTML.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '': - Usage() + if RAN.GeteNBIPAddress() == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': + HELP.GenericHelp(CONST.Version) + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or EPC.GetType() == '': + HELP.EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType()) + if RAN.GetranRepository() == '': + HELP.GitSrvHelp(RAN.GetranRepository(), RAN.GetranBranch(), RAN.GetranCommitID(), RAN.GetranAllowMerge(), RAN.GetranTargetBranch()) + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': + HELP.eNBSrvHelp(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath()) sys.exit('Insufficient Parameter') - if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): - SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") - SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") + if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/active_net_interfaces.awk", "/tmp") else: - if SSH.UEIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': - Usage() + if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': + HELP.GenericHelp(CONST.Version) sys.exit('UE: Insufficient Parameter') #read test_case_list.xml file # if no parameters for XML file, use default value - if (SSH.nbTestXMLfiles != 1): + if (HTML.GetnbTestXMLfiles() != 1): xml_test_file = cwd + "/test_case_list.xml" else: - xml_test_file = cwd + "/" + SSH.testXMLfiles[0] + xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0] xmlTree = ET.parse(xml_test_file) xmlRoot = xmlTree.getroot() exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') - if (SSH.nbTestXMLfiles == 1): - SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) + if (HTML.GetnbTestXMLfiles() == 1): + HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='Test-0')) repeatCount = xmlRoot.findtext('repeatCount',default='1') - SSH.repeatCounts.append(int(repeatCount)) + CiTestObj.repeatCounts.append(int(repeatCount)) all_tests=xmlRoot.findall('testCase') exclusion_tests=exclusion_tests.split() @@ -5136,8 +3540,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re else: logging.debug('ERROR: requested test is invalidly formatted: ' + test) sys.exit(1) - if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): - SSH.CheckFlexranCtrlInstallation() + if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): + CiTestObj.CheckFlexranCtrlInstallation() #get the list of tests to be done todo_tests=[] @@ -5150,108 +3554,125 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re signal.signal(signal.SIGUSR1, receive_signal) - SSH.CreateHtmlTabHeader() + if (CiTestObj.ADBIPAddress != 'none'): + terminate_ue_flag = False + CiTestObj.GetAllUEDevices(terminate_ue_flag) + CiTestObj.GetAllCatMDevices(terminate_ue_flag) + else: + CiTestObj.UEDevices.append('OAI-UE') + HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) + HTML.CreateHtmlTabHeader() - cnt = 0 - SSH.prematureExit = True - SSH.startTime = int(round(time.time() * 1000)) - while cnt < SSH.repeatCounts[0] and SSH.prematureExit: - SSH.prematureExit = False + CiTestObj.FailReportCnt = 0 + RAN.SetprematureExit(True) + HTML.SetstartTime(int(round(time.time() * 1000))) + while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): + RAN.SetprematureExit(False) + # At every iteratin of the retry loop, a separator will be added + # pass CiTestObj.FailReportCnt as parameter of HTML.CreateHtmlRetrySeparator + HTML.CreateHtmlRetrySeparator(CiTestObj.FailReportCnt) for test_case_id in todo_tests: - if SSH.prematureExit: + if RAN.GetprematureExit(): break for test in all_tests: - if SSH.prematureExit: + if RAN.GetprematureExit(): break id = test.get('id') if test_case_id != id: continue - SSH.testCase_id = id - SSH.desc = test.findtext('desc') + CiTestObj.testCase_id = id + HTML.SettestCase_id(CiTestObj.testCase_id) + EPC.SetTestCase_id(CiTestObj.testCase_id) + CiTestObj.desc = test.findtext('desc') + HTML.Setdesc(CiTestObj.desc) action = test.findtext('class') if (CheckClassValidity(action, id) == False): continue - SSH.ShowTestID() + CiTestObj.ShowTestID() GetParametersFromXML(action) if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': - if (SSH.ADBIPAddress != 'none'): + if (CiTestObj.ADBIPAddress != 'none'): terminate_ue_flag = False - SSH.GetAllUEDevices(terminate_ue_flag) + CiTestObj.GetAllUEDevices(terminate_ue_flag) if action == 'Build_eNB': - SSH.BuildeNB() + RAN.BuildeNB() elif action == 'WaitEndBuild_eNB': - SSH.WaitBuildeNBisFinished() + RAN.WaitBuildeNBisFinished() elif action == 'Initialize_eNB': - SSH.InitializeeNB() + check_eNB = False + check_OAI_UE = False + RAN.SetpStatus(CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE)) + + RAN.InitializeeNB() elif action == 'Terminate_eNB': - SSH.TerminateeNB() + RAN.TerminateeNB() elif action == 'Initialize_UE': - SSH.InitializeUE() + CiTestObj.InitializeUE() elif action == 'Terminate_UE': - SSH.TerminateUE() + CiTestObj.TerminateUE() elif action == 'Attach_UE': - SSH.AttachUE() + CiTestObj.AttachUE() elif action == 'Detach_UE': - SSH.DetachUE() + CiTestObj.DetachUE() elif action == 'DataDisable_UE': - SSH.DataDisableUE() + CiTestObj.DataDisableUE() elif action == 'DataEnable_UE': - SSH.DataEnableUE() + CiTestObj.DataEnableUE() elif action == 'CheckStatusUE': - SSH.CheckStatusUE() + CiTestObj.CheckStatusUE() elif action == 'Build_OAI_UE': - SSH.BuildOAIUE() + CiTestObj.BuildOAIUE() elif action == 'Initialize_OAI_UE': - SSH.InitializeOAIUE() + CiTestObj.InitializeOAIUE() elif action == 'Terminate_OAI_UE': - SSH.TerminateOAIUE() + CiTestObj.TerminateOAIUE() elif action == 'Initialize_CatM_module': - SSH.InitializeCatM() + CiTestObj.InitializeCatM() elif action == 'Terminate_CatM_module': - SSH.TerminateCatM() + CiTestObj.TerminateCatM() elif action == 'Attach_CatM_module': - SSH.AttachCatM() + CiTestObj.AttachCatM() elif action == 'Detach_CatM_module': - SSH.TerminateCatM() + CiTestObj.TerminateCatM() elif action == 'Ping_CatM_module': - SSH.PingCatM() + CiTestObj.PingCatM() elif action == 'Ping': - SSH.Ping() + CiTestObj.Ping() elif action == 'Iperf': - SSH.Iperf() + CiTestObj.Iperf() elif action == 'Reboot_UE': - SSH.RebootUE() + CiTestObj.RebootUE() elif action == 'Initialize_HSS': - SSH.InitializeHSS() + EPC.InitializeHSS() elif action == 'Terminate_HSS': - SSH.TerminateHSS() + EPC.TerminateHSS() elif action == 'Initialize_MME': - SSH.InitializeMME() + EPC.InitializeMME() elif action == 'Terminate_MME': - SSH.TerminateMME() + EPC.TerminateMME() elif action == 'Initialize_SPGW': - SSH.InitializeSPGW() + EPC.InitializeSPGW() elif action == 'Terminate_SPGW': - SSH.TerminateSPGW() + EPC.TerminateSPGW() elif action == 'Initialize_FlexranCtrl': - SSH.InitializeFlexranCtrl() + CiTestObj.InitializeFlexranCtrl() elif action == 'Terminate_FlexranCtrl': - SSH.TerminateFlexranCtrl() + CiTestObj.TerminateFlexranCtrl() elif action == 'IdleSleep': - SSH.IdleSleep() + CiTestObj.IdleSleep() elif action == 'Perform_X2_Handover': - SSH.Perform_X2_Handover() + CiTestObj.Perform_X2_Handover() else: sys.exit('Invalid action') - cnt += 1 - if cnt == SSH.repeatCounts[0] and SSH.prematureExit: - logging.debug('Testsuite failed ' + str(cnt) + ' time(s)') - SSH.CreateHtmlTabFooter(False) + CiTestObj.FailReportCnt += 1 + if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): + logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') + HTML.CreateHtmlTabFooter(False) sys.exit('Failed Scenario') else: - logging.info('Testsuite passed after ' + str(cnt) + ' time(s)') - SSH.CreateHtmlTabFooter(True) + logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') + HTML.CreateHtmlTabFooter(True) else: - Usage() + HELP.GenericHelp(CONST.Version) sys.exit('Invalid mode') sys.exit(0) diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py new file mode 100644 index 0000000000..350098e66e --- /dev/null +++ b/ci-scripts/ran.py @@ -0,0 +1,1051 @@ +#/* +# * 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 epc +import helpreadme as HELP +import constants as CONST +import html + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class RANManagement(): + + def __init__(self): + + self.prematureExit = False + 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.Build_eNB_args = '' + self.backgroundBuild = False + self.backgroundBuildTestId = ['', '', ''] + self.Build_eNB_forced_workspace_cleanup = False + self.Initialize_eNB_args = '' + self.air_interface = 'lte' + self.eNB_instance = '' + self.eNB_serverId = '' + self.eNBLogFiles = ['', '', ''] + self.eNBOptions = ['', '', ''] + self.eNBmbmsEnables = [False, False, False] + self.eNBstatuses = [-1, -1, -1] + self.flexranCtrlInstalled = False + self.flexranCtrlStarted = False + self.testCase_id = '' + self.epcPcapFile = '' + self.htmlObj = None + self.epcObj = None + +#----------------------------------------------------------- +# Setters and Getters on Public members +#----------------------------------------------------------- + + def SetHtmlObj(self, obj): + self.htmlObj = obj + def SetEpcObj(self, obj): + self.epcObj = obj + + def SetflexranCtrlInstalled(self,fxrctin): + self.flexranCtrlInstalled = fxrctin + def GetflexranCtrlInstalled(self): + return self.flexranCtrlInstalled + def SetflexranCtrlStarted(self,fxrctst): + self.flexranCtrlStarted = fxrctst + def GetflexranCtrlStarted(self): + return self.flexranCtrlStarted + def SetpStatus(self, pSt): + self.pStatus = pSt + def SetranRepository(self, repository): + self.ranRepository = repository + def GetranRepository(self): + return self.ranRepository + def SetranBranch(self, branch): + self.ranBranch = branch + def GetranBranch(self): + return self.ranBranch + def SetranCommitID(self, commitid): + self.ranCommitID = commitid + def GetranCommitID(self): + return self.ranCommitID + def SeteNB_serverId(self, enbsrvid): + self.eNB_serverId = enbsrvid + def GeteNB_serverId(self): + return self.eNB_serverId + def SeteNBIPAddress(self, enbip): + self.eNBIPAddress = enbip + def GeteNBIPAddress(self): + return self.eNBIPAddress + def SeteNBUserName(self, enbusr): + self.eNBUserName = enbusr + def GeteNBUserName(self): + return self.eNBUserName + def SeteNBPassword(self, enbpw): + self.eNBPassword = enbpw + def GeteNBPassword(self): + return self.eNBPassword + def SeteNBSourceCodePath(self, enbcodepath): + self.eNBSourceCodePath = enbcodepath + def GeteNBSourceCodePath(self): + return self.eNBSourceCodePath + def SetranAllowMerge(self, merge): + self.ranAllowMerge = merge + def GetranAllowMerge(self): + return self.ranAllowMerge + def SetranTargetBranch(self, tbranch): + self.ranTargetBranch = tbranch + def GetranTargetBranch(self): + return self.ranTargetBranch + def SetBuild_eNB_args(self, enbbuildarg): + self.Build_eNB_args = enbbuildarg + def GetBuild_eNB_args(self): + return self.Build_eNB_args + def SetInitialize_eNB_args(self, initenbarg): + self.Initialize_eNB_args = initenbarg + def GetInitialize_eNB_args(self): + return self.Initialize_eNB_args + def SetbackgroundBuild(self, bkbuild): + self.backgroundBuild = bkbuild + def GetbackgroundBuild(self): + return self.backgroundBuild + def SetbackgroundBuildTestId(self, bkbuildid): + self.backgroundBuildTestId = bkbuildid + def GetbackgroundBuildTestId(self): + return self.backgroundBuildTestId + def SetBuild_eNB_forced_workspace_cleanup(self, fcdwspclean): + self.Build_eNB_forced_workspace_cleanup = fcdwspclean + def GetBuild_eNB_forced_workspace_cleanup(self): + return self.Build_eNB_forced_workspace_cleanup + def Setair_interface(self, airif): + self.air_interface = airif + def Getair_interface(self): + return self.air_interface + def SeteNB_instance(self, enbinst): + self.eNB_instance = enbinst + def GeteNB_instance(self): + return self.eNB_instance + + def SeteNBLogFile(self, enblog, idx): + self.eNBLogFiles[idx] = enblog + def GeteNBLogFile(self, idx): + return self.eNBLogFiles[idx] + + def GeteNBmbmsEnable(self, idx): + return self.eNBmbmsEnables[idx] + + def SeteNB1IPAddress(self,enb1ip): + self.eNB1IPAddress = enb1ip + def GeteNB1IPAddress(self): + return self.eNB1IPAddress + def SeteNB1UserName(self, enb1usr): + self.eNB1UserName = enb1usr + def GeteNB1UserName(self): + return self.eNB1UserName + def SeteNB1Password(self, enb1pw): + self.eNB1Password = enb1pw + def GeteNB1Password(self): + return self.eNB1Password + def SeteNB1SourceCodePath(self, enb1codepath): + self.eNB1SourceCodePath = enb1codepath + def GeteNB1SourceCodePath(self): + return self.eNB1SourceCodePath + + def SeteNB2IPAddress(self, enb2ip): + self.eNB2IPAddress = enb2ip + def GeteNB2IPAddress(self): + return self.eNB2IPAddress + def SeteNB2UserName(self, enb2usr): + self.eNB2UserName = enb2usr + def GeteNB2UserName(self): + return self.eNB2UserName + def SeteNB2Password(self, enb2pw): + self.eNB2Password = enb2pw + def GeteNB2Password(self): + return self.eNB2Password + def SeteNB2SourceCodePath(self, enb2codepath): + self.eNB2SourceCodePath = enb2codepath + def GeteNB2SourceCodePath(self): + return self.eNB2SourceCodePath + + def SetprematureExit(self, premex): + self.prematureExit = premex + def GetprematureExit(self): + return self.prematureExit + +#----------------------------------------------------------- +# RAN management functions +#----------------------------------------------------------- + + def BuildeNB(self): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + HELP.GenericHelp(CONST.Version) + sys.exit('Insufficient Parameter') + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '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') + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + # Check if we build an 5G-NR gNB or an LTE eNB + result = re.search('--gNB', self.Build_eNB_args) + if result is not None: + self.air_interface = 'nr' + else: + self.air_interface = 'lte' + # 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.GettestCase_id() + else: + self.testCase_id = '000000' + # 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) + # Checking the BUILD INFO file + if not self.backgroundBuild: + mySSH.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', mySSH.getBefore()) + if result is not None: + mismatch = False + mySSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(self.ranCommitID, mySSH.getBefore()) + if result is None: + mismatch = True + mySSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + result = re.search('YES', mySSH.getBefore()) + if result is None: + mismatch = True + mySSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + result = re.search('develop', mySSH.getBefore()) + else: + result = re.search(self.ranTargetBranch, mySSH.getBefore()) + if result is None: + mismatch = True + else: + result = re.search('NO', mySSH.getBefore()) + if result is None: + 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) + return + + mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + # 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 + if (self.ranAllowMerge): + 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) + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('mkdir -p log', '\$', 5) + mySSH.command('chmod 777 log', '\$', 5) + # no need to remove in log (git clean did the trick) + if self.backgroundBuild: + mySSH.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) + mySSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) + mySSH.close() + if self.htmlObj is not None: + self.htmlObj.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) + + def WaitBuildeNBisFinished(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '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') + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + count = 40 + buildOAIprocess = True + while (count > 0) and buildOAIprocess: + mySSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) + result = re.search('build_oai', mySSH.getBefore()) + if result is None: + buildOAIprocess = False + else: + count -= 1 + time.sleep(30) + mySSH.close() + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) + + def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): + if self.htmlObj is not None: + self.htmlObj.SettestCase_id(testcaseId) + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) + mySSH.command('ls ran_build/build', '\$', 3) + mySSH.command('ls ran_build/build', '\$', 3) + if self.air_interface == 'nr': + nodeB_prefix = 'g' + else: + nodeB_prefix = 'e' + buildStatus = True + result = re.search(self.air_interface + '-softmodem', mySSH.getBefore()) + if result is None: + buildStatus = False + else: + # Generating a BUILD INFO file + mySSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + mySSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + mySSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + mySSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + mySSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + mySSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + 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': + 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) + mySSH.close() + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + os.remove('./tmp_build' + testcaseId + '.zip') + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') + os.remove('./tmp_build' + testcaseId + '.zip') + mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + mySSH.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) + mySSH.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) + mySSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) + mySSH.close() + else: + mySSH.close() + + if buildStatus: + logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + else: + logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB 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) + sys.exit(1) + + def InitializeeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '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') + + if self.htmlObj is not None: + self.testCase_id = self.htmlObj.GettestCase_id() + else: + self.testCase_id = '000000' + mySSH = SSH.SSHConnection() + + if (self.pStatus < 0): + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', self.pStatus) + self.htmlObj.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.GetIPAddress() + localEpcUserName = self.epcObj.GetUserName() + localEpcPassword = self.epcObj.GetPassword() + 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()) + if result is not None: + eth_interface = result.group('eth_interface') + logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') + self.epcPcapFile = 'enb_' + self.testCase_id + '_s1log.pcap' + mySSH.command('echo ' + localEpcPassword + ' | sudo -S rm -f /tmp/' + self.epcPcapFile , '\$', 5) + mySSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.epcPcapFile + ' > /tmp/tshark.log 2>&1 &', localEpcUserName, 5) + mySSH.close() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath, '\$', 5) + # Initialize_eNB_args usually start with -O and followed by the location in repository + full_config_file = self.Initialize_eNB_args.replace('-O ','') + extra_options = '' + extIdx = full_config_file.find('.conf') + if (extIdx > 0): + extra_options = full_config_file[extIdx + 5:] + # if tracer options is on, compiling and running T Tracer + result = re.search('T_stdout', str(extra_options)) + if result is not None: + logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') + mySSH.command('cd common/utils/T/tracer', '\$', 5) + mySSH.command('make', '\$', 10) + mySSH.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) + mySSH.command('cd ' + lSourcePath, '\$', 5) + full_config_file = full_config_file[:extIdx + 5] + config_path, config_file = os.path.split(full_config_file) + else: + sys.exit('Insufficient Parameter') + ci_full_config_file = config_path + '/ci-' + config_file + rruCheck = False + result = re.search('^rru|^rcc|^du.band', str(config_file)) + if result is not None: + rruCheck = True + # do not reset board twice in IF4.5 case + result = re.search('^rru|^enb|^du.band', str(config_file)) + if result is not None: + mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) + result = re.search('type: b200', mySSH.getBefore()) + if result is not None: + logging.debug('Found a B2xx device --> resetting it') + mySSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + # Reloading FGPA bin firmware + 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: + localEpcIpAddr = self.epcObj.GetIPAddress() + mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + localEpcIpAddr + '/\' ' + 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_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); + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + 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 + mySSH.command('grep enable_enb_m2 ' + ci_full_config_file, '\$', 2); + result = re.search('yes', mySSH.getBefore()) + if result is not None: + self.eNBmbmsEnables[int(self.eNB_instance)] = True + logging.debug('\u001B[1m MBMS is enabled on this eNB\u001B[0m') + result = re.search('noS1', str(self.Initialize_eNB_args)) + eNBinNoS1 = False + if result is not None: + eNBinNoS1 = True + logging.debug('\u001B[1m eNB is in noS1 configuration \u001B[0m') + # Launch eNB with the modified config file + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + mySSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('hostnamectl','\$', 5) + result = re.search('CentOS Linux 7', mySSH.getBefore()) + if result is not None: + mySSH.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) + else: + mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' + if extra_options != '': + self.eNBOptions[int(self.eNB_instance)] = extra_options + time.sleep(6) + doLoop = True + loopCounter = 20 + enbDidSync = False + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # In case of T tracer recording, we may need to kill it + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + mySSH.command('killall --signal SIGKILL record', '\$', 5) + mySSH.close() + doLoop = False + logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('-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.GetIPAddress() + localEpcUserName = self.epcObj.GetUserName() + localEpcPassword = self.epcObj.GetPassword() + mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + if self.epcPcapFile != '': + time.sleep(0.5) + mySSH.command('echo ' + localEpcPassword + ' | sudo -S chmod 666 /tmp/' + self.epcPcapFile, '\$', 5) + mySSH.close() + time.sleep(1) + if self.epcPcapFile != '': + copyin_res = mySSH.copyin(localEpcIpAddr, localEpcUserName, localEpcPassword, '/tmp/' + self.epcPcapFile, '.') + if (copyin_res == 0): + mySSH.copyout(lIpAddr, lUserName, lPassWord, self.epcPcapFile, lSourcePath + '/cmake_targets/.') + self.prematureExit = True + return + else: + mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) + if rruCheck: + result = re.search('wait RUs', mySSH.getBefore()) + else: + result = re.search('got sync|Starting F1AP at CU', mySSH.getBefore()) + if result is None: + time.sleep(6) + else: + doLoop = False + enbDidSync = True + time.sleep(10) + + if enbDidSync and eNBinNoS1: + mySSH.command('ifconfig oaitun_enb1', '\$', 4) + mySSH.command('ifconfig oaitun_enb1', '\$', 4) + result = re.search('inet addr:1|inet 1', mySSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_enb1 interface is mounted and configured\u001B[0m') + else: + logging.error('\u001B[1m oaitun_enb1 interface is either NOT mounted or NOT configured\u001B[0m') + if self.eNBmbmsEnables[int(self.eNB_instance)]: + mySSH.command('ifconfig oaitun_enm1', '\$', 4) + result = re.search('inet addr', mySSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_enm1 interface is mounted and configured\u001B[0m') + 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) + + mySSH.close() + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) + logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') + + def CheckeNBProcess(self, status_queue): + try: + # At least the instance 0 SHALL be on! + if self.eNBstatuses[0] == 0: + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + elif self.eNBstatuses[0] == 1: + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + elif self.eNBstatuses[0] == 2: + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + else: + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5) + result = re.search(self.air_interface + '-softmodem', mySSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') + status_queue.put(CONST.ENB_PROCESS_FAILED) + else: + status_queue.put(CONST.ENB_PROCESS_OK) + mySSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def TerminateeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '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') + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + if self.air_interface == 'lte': + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' + mySSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-softmodem', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5) + time.sleep(10) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-softmodem', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5) + time.sleep(5) + mySSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + 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.GetIPAddress() + localEpcUserName = self.epcObj.GetUserName() + localEpcPassword = self.epcObj.GetPassword() + mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + time.sleep(1) + if self.epcPcapFile != '': + mySSH.command('echo ' + localEpcPassword + ' | sudo -S chmod 666 /tmp/' + self.epcPcapFile, '\$', 5) + mySSH.copyin(localEpcIpAddr, localEpcUserName, localEpcPassword, '/tmp/' + self.epcPcapFile, '.') + mySSH.copyout(lIpAddr, lUserName, lPassWord, self.epcPcapFile, lSourcePath + '/cmake_targets/.') + mySSH.close() + logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) + enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] + raw_record_file = enbLogFile.replace('.log', '_record.raw') + replay_log_file = enbLogFile.replace('.log', '_replay.log') + extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') + extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') + mySSH.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) + mySSH.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) + mySSH.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) + 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('N/A', 'OK', CONST.ALL_PROCESSES_OK) + self.eNBLogFiles[int(self.eNB_instance)] = '' + else: + analyzeFile = False + if self.eNBLogFiles[int(self.eNB_instance)] != '': + analyzeFile = True + fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] + self.eNBLogFiles[int(self.eNB_instance)] = '' + if analyzeFile: + 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.SetHmleNBFailureMsg('Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!') + self.htmlObj.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + self.eNBmbmsEnables[int(self.eNB_instance)] = False + return + if self.eNB_serverId != '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) + if (logStatus < 0): + if self.htmlObj is not None: + self.htmlObj.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('N/A', 'OK', CONST.ALL_PROCESSES_OK) + else: + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + self.eNBmbmsEnables[int(self.eNB_instance)] = False + self.eNBstatuses[int(self.eNB_instance)] = -1 + + def LogCollecteNB(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + mySSH.command('cd ' + self.eNBSourceCodePath, '\$', 5) + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) + mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) + 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): + if (not os.path.isfile('./' + eNBlogFile)): + return -1 + enb_log_file = open('./' + eNBlogFile, 'r') + exitSignalReceived = False + foundAssertion = False + msgAssertion = '' + msgLine = 0 + foundSegFault = False + foundRealTimeIssue = False + rrcSetupComplete = 0 + rrcReleaseRequest = 0 + rrcReconfigRequest = 0 + rrcReconfigComplete = 0 + rrcReestablishRequest = 0 + rrcReestablishComplete = 0 + rrcReestablishReject = 0 + rlcDiscardBuffer = 0 + rachCanceledProcedure = 0 + uciStatMsgCount = 0 + pdcpFailure = 0 + ulschFailure = 0 + ulschReceiveOK = 0 + cdrxActivationMessageCount = 0 + dropNotEnoughRBs = 0 + mbmsRequestMsg = 0 + htmleNBFailureMsg = '' + isRRU = False + isSlave = False + slaveReceivesFrameResyncCmd = False + X2HO_state = CONST.X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures = 0 + X2HO_outNbProcedures = 0 + for line in enb_log_file.readlines(): + if X2HO_state == CONST.X2_HO_REQ_STATE__IDLE: + result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) + if result is not None: + X2HO_state = CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ + result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) + if result is not None: + X2HO_state = CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK + if X2HO_state == CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: + result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) + if result is not None: + X2HO_state = CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE + if X2HO_state == CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: + result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) + if result is not None: + X2HO_state = CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ + if X2HO_state == CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: + result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) + if result is not None: + X2HO_state = CONST.X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures += 1 + if X2HO_state == CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: + result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) + if result is not None: + X2HO_state = CONST.X2_HO_REQ_STATE__IDLE + X2HO_outNbProcedures += 1 + + if self.eNBOptions[int(self.eNB_instance)] != '': + res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[int(self.eNB_instance)]) + res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) + if res1 is not None and res2 is not None: + requested_option = int(res1.group('requested_option')) + applied_option = int(res2.group('applied_option')) + if requested_option == applied_option: + htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + else: + htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + result = re.search('Exiting OAI softmodem', str(line)) + if result is not None: + exitSignalReceived = True + result = re.search('[Ss]egmentation [Ff]ault', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('[Cc]ore [dD]ump', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('./ran_build/build/lte-softmodem', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('[Aa]ssertion', str(line)) + if result is not None and not exitSignalReceived: + foundAssertion = True + result = re.search('LLL', str(line)) + if result is not None and not exitSignalReceived: + foundRealTimeIssue = True + if foundAssertion and (msgLine < 3): + msgLine += 1 + msgAssertion += str(line) + result = re.search('Setting function for RU', str(line)) + if result is not None: + isRRU = True + if isRRU: + result = re.search('RU 0 is_slave=yes', str(line)) + if result is not None: + isSlave = True + if isSlave: + result = re.search('Received RRU_frame_resynch command', str(line)) + if result is not None: + slaveReceivesFrameResyncCmd = True + result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) + if result is not None: + rrcSetupComplete += 1 + result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) + if result is not None: + rrcReleaseRequest += 1 + result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) + if result is not None: + rrcReconfigRequest += 1 + result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) + if result is not None: + rrcReconfigComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) + if result is not None: + rrcReestablishRequest += 1 + result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) + if result is not None: + rrcReestablishComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) + if result is not None: + rrcReestablishReject += 1 + result = re.search('CDRX configuration activated after RRC Connection', str(line)) + if result is not None: + cdrxActivationMessageCount += 1 + result = re.search('uci->stat', str(line)) + if result is not None: + uciStatMsgCount += 1 + result = re.search('PDCP.*Out of Resources.*reason', str(line)) + if result is not None: + pdcpFailure += 1 + result = re.search('ULSCH in error in round', str(line)) + if result is not None: + ulschFailure += 1 + result = re.search('ULSCH received ok', str(line)) + if result is not None: + ulschReceiveOK += 1 + result = re.search('BAD all_segments_received', str(line)) + if result is not None: + rlcDiscardBuffer += 1 + result = re.search('Canceled RA procedure for UE rnti', str(line)) + if result is not None: + rachCanceledProcedure += 1 + result = re.search('dropping, not enough RBs', str(line)) + if result is not None: + dropNotEnoughRBs += 1 + if self.eNBmbmsEnables[int(self.eNB_instance)]: + result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line)) + if result is not None: + mbmsRequestMsg += 1 + enb_log_file.close() + logging.debug(' File analysis completed') + if self.air_interface == 'lte': + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' + if self.air_interface == 'nr': + if ulschReceiveOK > 0: + statMsg = nodeB_prefix + 'NB showed ' + str(ulschReceiveOK) + ' "ULSCH received ok" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + htmleNBFailureMsg += statMsg + '\n' + if uciStatMsgCount > 0: + statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + htmleNBFailureMsg += statMsg + '\n' + if pdcpFailure > 0: + statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + htmleNBFailureMsg += statMsg + '\n' + if ulschFailure > 0: + statMsg = nodeB_prefix + 'NB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + htmleNBFailureMsg += statMsg + '\n' + if dropNotEnoughRBs > 0: + statMsg = 'eNB showed ' + str(dropNotEnoughRBs) + ' "dropping, not enough RBs" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + htmleNBFailureMsg += statMsg + '\n' + if rrcSetupComplete > 0: + rrcMsg = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' RRC Connection Setup(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + if rrcReleaseRequest > 0: + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + if self.eNBmbmsEnables[int(self.eNB_instance)]: + if mbmsRequestMsg > 0: + rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_inNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_outNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + if self.eNBOptions[int(self.eNB_instance)] != '': + res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) + if res1 is not None: + if cdrxActivationMessageCount > 0: + rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + else: + rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' + logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') + htmleNBFailureMsg += rrcMsg + '\n' + if rachCanceledProcedure > 0: + rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' + logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') + htmleNBFailureMsg += rachMsg + '\n' + if isRRU: + if isSlave: + if slaveReceivesFrameResyncCmd: + rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') + htmleNBFailureMsg += rruMsg + '\n' + else: + rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') + htmleNBFailureMsg += rruMsg + '\n' + self.prematureExit(True) + return CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED + if foundSegFault: + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m') + if self.htmlObj is not None: + self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) + return CONST.ENB_PROCESS_SEG_FAULT + if foundAssertion: + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m') + htmleNBFailureMsg += msgAssertion + if self.htmlObj is not None: + self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) + return CONST.ENB_PROCESS_ASSERTION + if foundRealTimeIssue: + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') + htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' + #return CONST.ENB_PROCESS_REALTIME_ISSUE + if rlcDiscardBuffer > 0: + rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' + logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') + htmleNBFailureMsg += rlcMsg + '\n' + if self.htmlObj is not None: + self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) + return CONST.ENB_PROCESS_REALTIME_ISSUE + if self.htmlObj is not None: + self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) + return 0 diff --git a/ci-scripts/reportBuildLocally.sh b/ci-scripts/reportBuildLocally.sh index 54372ac6ba..0a75ff25b7 100755 --- a/ci-scripts/reportBuildLocally.sh +++ b/ci-scripts/reportBuildLocally.sh @@ -492,6 +492,77 @@ function report_build { awk '{print " "$1""}' ./oai_rules_result_list.txt >> ./build_results.html echo " " >> ./build_results.html echo "
" >> ./build_results.html + echo "
" >> ./build_results.html + fi + if [ -f ./header-files-w-incorrect-define.txt ] + then + NB_FILES_IN_ERROR=`wc -l ./header-files-w-incorrect-define.txt | sed -e "s@ .*@@"` + if [ $NB_FILES_IN_ERROR -eq 0 ] + then + echo "
" >> ./build_results.html + if [ $MR_TRIG -eq 1 ]; then echo " No Issue for CIRCULAR DEPENDENCY PROTECTION in modified files" >> ./build_results.html; fi + if [ $PU_TRIG -eq 1 ]; then echo " No Issue for CIRCULAR DEPENDENCY PROTECTION in the whole repository" >> ./build_results.html; fi + echo "
" >> ./build_results.html + else + echo "
" >> ./build_results.html + if [ $MR_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} modified files MAY NOT HAVE CIRCULAR DEPENDENCY PROTECTION" >> ./build_results.html; fi + if [ $PU_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} files in repository MAY NOT HAVE CIRCULAR DEPENDENCY PROTECTION in the whole repository" >> ./build_results.html; fi + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + awk '{if($0 ~/error in/){print " "};if($0 ~/files with same/){print " "}}' ./header-files-w-incorrect-define.txt >> ./build_results.html + echo "
Potential IssueImpacted FileIncorrect Macro
error in declaration"$4""$5"
files with same #define"$5""$6"
" >> ./build_results.html + echo "
" >> ./build_results.html + echo "
" >> ./build_results.html + fi + fi + if [ -f ./files-w-gnu-gpl-license-banner.txt ] + then + NB_FILES_IN_ERROR=`wc -l ./files-w-gnu-gpl-license-banner.txt | sed -e "s@ .*@@"` + if [ $NB_FILES_IN_ERROR -ne 0 ] + then + echo "
" >> ./build_results.html + if [ $MR_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} modified files HAVE a GNU GPL license banner" >> ./build_results.html; fi + if [ $PU_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} files in repository HAVE a GNU GPL license banner" >> ./build_results.html; fi + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + awk '{print " "}' ./files-w-gnu-gpl-license-banner.txt >> ./build_results.html + echo "
Filename
"$1"
" >> ./build_results.html + echo "
" >> ./build_results.html + echo "
" >> ./build_results.html + fi + fi + if [ -f ./files-w-suspect-banner.txt ] + then + NB_FILES_IN_ERROR=`wc -l ./files-w-suspect-banner.txt | sed -e "s@ .*@@"` + if [ $NB_FILES_IN_ERROR -ne 0 ] + then + echo "
" >> ./build_results.html + if [ $MR_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} modified files HAVE a suspect license banner" >> ./build_results.html; fi + if [ $PU_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} files in repository HAVE a suspect license banner" >> ./build_results.html; fi + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + awk '{print " "}' ././files-w-suspect-banner.txt >> ./build_results.html + echo "
Filename
"$1"
" >> ./build_results.html + echo "
" >> ./build_results.html + echo "
" >> ./build_results.html + fi fi fi diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 502c1a5d47..64af11c8ba 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -342,34 +342,8 @@ function check_iperf { local FILE_COMPLETE=`egrep -c "Server Report" ${LOC_BASE_LOG}_client.txt` if [ $FILE_COMPLETE -eq 0 ] then - # This part will become obsolete once we have UL - if [[ $LOC_IS_RF_SIM -eq 1 ]] && [[ $LOC_IS_NR -eq 1 ]] - then - echo "no UL integration right now --> normal to have no server report" - if [ -f ${LOC_BASE_LOG}_server.txt ] - then - local EFFECTIVE_BANDWIDTH=`tail -n1 ${LOC_BASE_LOG}_server.txt | sed -e "s#^.*MBytes *##" -e "s#^.*KBytes *##" -e "s#sec.*#sec#"` - if [[ $2 =~ .*K.* ]] - then - local BW_PREFIX="K" - else - local BW_PREFIX="M" - fi - if [[ $EFFECTIVE_BANDWIDTH =~ .*${LOC_REQ_BW}.*${BW_PREFIX}bits.* ]] || [[ $EFFECTIVE_BANDWIDTH =~ .*${LOC_REQ_BW_MINUS_ONE}.*${BW_PREFIX}bits.* ]] - then - echo "got requested DL bandwidth: $EFFECTIVE_BANDWIDTH" - else - echo "got LESS than requested DL bandwidth: $EFFECTIVE_BANDWIDTH" - IPERF_STATUS=-1 - fi - else - IPERF_STATUS=-1 - echo "Server File Report not found" - fi - else - IPERF_STATUS=-1 - echo "File Report not found" - fi + IPERF_STATUS=-1 + echo "File Report not found" else if [ `egrep -c "Mbits/sec" ${LOC_BASE_LOG}_client.txt` -ne 0 ] then @@ -2044,81 +2018,117 @@ function run_test_on_vm { if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf-sim.* ]] then - NR_STATUS=0 - PING_STATUS=0 - IPERF_STATUS=0 - CN_CONFIG="noS1" CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf S1_NOS1_CFG=0 PRB=106 FREQUENCY=3510 + local try_cnt="0" + NR_STATUS=0 + ######### start of loop + while [ $try_cnt -lt 5 ] + do + SYNC_STATUS=0 + PING_STATUS=0 + IPERF_STATUS=0 - echo "############################################################" - echo "${CN_CONFIG} : Starting the gNB" - echo "############################################################" - CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log - start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG + echo "############################################################" + echo "${CN_CONFIG} : Starting the gNB" + echo "############################################################" + CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log + start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG - echo "############################################################" - echo "${CN_CONFIG} : Starting the NR-UE" - echo "############################################################" - CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log - start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG - if [ $NR_UE_SYNC -eq 0 ] - then - echo "Problem w/ gNB and NR-UE not syncing" + echo "############################################################" + echo "${CN_CONFIG} : Starting the NR-UE" + echo "############################################################" + CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log + start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG + if [ $NR_UE_SYNC -eq 0 ] + then + echo "Problem w/ gNB and NR-UE not syncing" + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + SYNC_STATUS=-1 + try_cnt=$[$try_cnt+1] + continue + fi + + echo "############################################################" + echo "${CN_CONFIG} : Pinging the gNB from NR-UE" + echo "############################################################" + get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR + PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log + ping_epc_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $ENB_IP_ADDR $PING_LOG_FILE 1 0 + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC + check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 + + echo "############################################################" + echo "${CN_CONFIG} : Pinging the NR-UE from gNB" + echo "############################################################" + get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 + PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log + ping_enb_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR $UE_IP_ADDR $PING_LOG_FILE 0 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC + check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 + + echo "############################################################" + echo "${CN_CONFIG} : iperf DL -- NR-UE is server and gNB is client" + echo "############################################################" + THROUGHPUT="30K" + CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_dl + get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR + get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 + generic_iperf $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_client.txt $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_server.txt $ARCHIVES_LOC + check_iperf $ARCHIVES_LOC/$CURR_IPERF_LOG_BASE $THROUGHPUT + if [ $IPERF_STATUS -ne 0 ] + then + echo "DL test not OK" + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + try_cnt=$[$try_cnt+1] + continue + fi + + echo "############################################################" + echo "${CN_CONFIG} : iperf UL -- gNB is server and NR-UE is client" + echo "############################################################" + THROUGHPUT="30K" + CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_ul + get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR + get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 + generic_iperf $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_server.txt $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_client.txt $ARCHIVES_LOC + check_iperf $ARCHIVES_LOC/$CURR_IPERF_LOG_BASE $THROUGHPUT + + echo "############################################################" + echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators" + echo "############################################################" terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 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 - echo "5G-NR RFSIM seems to FAIL" - echo "5G-NR: TEST_KO" >> $ARCHIVES_LOC/test_final_status.log - STATUS=-1 - return - fi - - echo "############################################################" - echo "${CN_CONFIG} : iperf DL -- NR-UE is server and gNB is client" - echo "############################################################" - THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_dl - get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR - get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 - generic_iperf $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 - scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_client.txt $ARCHIVES_LOC - scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_server.txt $ARCHIVES_LOC - check_iperf $ARCHIVES_LOC/$CURR_IPERF_LOG_BASE $THROUGHPUT - - echo "############################################################" - echo "${CN_CONFIG} : iperf UL -- gNB is server and NR-UE is client" - echo "############################################################" - THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_ul - get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR - get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 - generic_iperf $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 - scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_server.txt $ARCHIVES_LOC - scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_client.txt $ARCHIVES_LOC - check_iperf $ARCHIVES_LOC/$CURR_IPERF_LOG_BASE $THROUGHPUT - - echo "############################################################" - echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators" - echo "############################################################" - terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 - 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 - + if [ $IPERF_STATUS -ne 0 ] + then + echo "UL test not OK" + try_cnt=$[$try_cnt+1] + else + try_cnt=$[$try_cnt+10] + fi + done ######### end of loop full_l2_sim_destroy + echo "############################################################" echo "Checking run status" echo "############################################################" + if [ $SYNC_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $PING_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $IPERF_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $NR_STATUS -eq 0 ] diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py new file mode 100644 index 0000000000..68a1d7836c --- /dev/null +++ b/ci-scripts/sshconnection.py @@ -0,0 +1,217 @@ +#/* +# * 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 pexpect # pexpect +import logging +import time # sleep +import re +import sys + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class SSHConnection(): + def __init__(self): + self.ssh = '' + self.picocom_closure = False + + def disablePicocomClosure(self): + self.picocom_closure = False + + def enablePicocomClosure(self): + self.picocom_closure = True + + def open(self, ipaddress, username, password): + count = 0 + connect_status = False + while count < 4: + self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress], timeout = 5) + self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + self.ssh.sendline('yes') + self.ssh.expect('password:') + self.ssh.sendline(password) + self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + count = 10 + connect_status = True + else: + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + elif self.sshresponse == 1: + self.ssh.sendline(password) + self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + count = 10 + connect_status = True + else: + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + elif self.sshresponse == 2: + # Checking if we are really on the remote client defined by its IP address + self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) + result = re.search(str(ipaddress), str(self.ssh.before)) + if result is None: + self.close() + else: + count = 10 + connect_status = True + else: + # debug output + logging.debug(str(self.ssh.before)) + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + # adding a tempo when failure + if not connect_status: + time.sleep(1) + count += 1 + if connect_status: + pass + else: + sys.exit('SSH Connection Failed') + + def command(self, commandline, expectedline, timeout): + logging.debug(commandline) + self.ssh.timeout = timeout + self.ssh.sendline(commandline) + self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + return 0 + elif self.sshresponse == 1: + logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + logging.debug(str(self.ssh.before)) + sys.exit(self.sshresponse) + elif self.sshresponse == 2: + logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + result = re.search('ping |iperf |picocom', str(commandline)) + if result is None: + logging.debug(str(self.ssh.before)) + sys.exit(self.sshresponse) + else: + return -1 + else: + logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + sys.exit(self.sshresponse) + + def close(self): + self.ssh.timeout = 5 + self.ssh.sendline('exit') + self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + pass + elif self.sshresponse == 1: + if not self.picocom_closure: + logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') + else: + logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') + + def copyin(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False + logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination) + while count < 10: + scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True + else: + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: + return 0 + else: + return -1 + + def copyout(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False + logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination) + while count < 4: + scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True + else: + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: + pass + else: + sys.exit('SCP failed') + + def getBefore(self): + return str(self.ssh.before) diff --git a/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml index 680f09c435..611492b0bc 100644 --- a/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml +++ b/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml @@ -24,7 +24,7 @@ test-lte-m-10-tm1 Test-LTE-M-10MHz-TM1 tasks - 2 + 1 030201 040102 diff --git a/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml index 2a035396c5..09aa0b04a2 100644 --- a/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml +++ b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml @@ -25,7 +25,7 @@ test-05-tm2 Test-05MHz-TM2 tasks - 3 + 2 030201 040101 diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index ebd6f88fc2..50a38dada2 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -727,7 +727,6 @@ Message("CPU_Affinity flag is ${CPU_AFFINITY}") ############################################################## add_boolean_option(NO_RRM True "DO WE HAVE A RADIO RESSOURCE MANAGER: NO") -add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "set the RLC mode to AM for the default bearer") add_boolean_option(OAI_NW_DRIVER_TYPE_ETHERNET False "????") add_boolean_option(DEADLINE_SCHEDULER True "Use the Linux scheduler SCHED_DEADLINE: kernel >= 3.14") @@ -828,7 +827,7 @@ add_boolean_option(TRACE_RLC_UM_TX_STATUS False "TRACE for RLC UM, TO BE CHANGE ########################## # RRC LAYER OPTIONS ########################## -add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "Otherwise it is UM, configure params are actually set in rrc_eNB.c:rrc_eNB_generate_defaultRRCConnectionReconfiguration(...)") +add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the RLC mode to AM for the default bearer, otherwise it is UM.") ########################## @@ -884,6 +883,7 @@ include_directories("${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0") include_directories("${OPENAIR2_DIR}/RRC/LTE/MESSAGES") include_directories("${OPENAIR2_DIR}/RRC/LTE") include_directories("${OPENAIR_DIR}/common/utils") +include_directories("${OPENAIR_DIR}/common/utils/collection") include_directories("${OPENAIR_DIR}/common/utils/ocp_itti") include_directories("${OPENAIR3_DIR}/NAS/COMMON") include_directories("${OPENAIR3_DIR}/NAS/COMMON/API/NETWORK") @@ -1330,6 +1330,9 @@ add_library(ldpc MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} ) add_library(coding MODULE ${PHY_TURBOSRC} ) +add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ) + + set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c @@ -1370,7 +1373,7 @@ set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c - ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c + ${OPENAIR1_DIR}/PHY/TOOLS/dfts_load.c ${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c ${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c ${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c @@ -1495,6 +1498,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c + ${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/filt16a_32.c @@ -1587,7 +1591,9 @@ endif () add_library(PHY_COMMON ${PHY_SRC_COMMON}) add_dependencies(PHY_COMMON rrc_flag) +add_dependencies(PHY_COMMON dfts) add_library(PHY ${PHY_SRC}) + add_dependencies(PHY rrc_flag) add_library(PHY_UE ${PHY_SRC_UE}) add_dependencies(PHY_UE rrc_flag) @@ -1638,7 +1644,7 @@ set(NR_RRC_DIR ${OPENAIR2_DIR}/RRC/NR) set(NR_UE_RRC_DIR ${OPENAIR2_DIR}/RRC/NR_UE) set(PDCP_DIR ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0) -set(LTE_RLC_SRC +set(RLC_V1 ${RLC_AM_DIR}/rlc_am.c ${RLC_AM_DIR}/rlc_am_init.c ${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c @@ -1668,6 +1674,17 @@ set(LTE_RLC_SRC ${RLC_DIR}/rlc_mpls.c ) +set(RLC_V2 + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_oai_api.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/asn1_utils.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_ue_manager.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_entity.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_entity_am.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_entity_um.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_pdu.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_sdu.c + ) + set(NR_RLC_SRC ${OPENAIR2_DIR}/LAYER2/nr_rlc/asn1_utils.c ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity.c @@ -1702,7 +1719,7 @@ set(L2_SRC ) set(L2_LTE_SRC - ${LTE_RLC_SRC} + ${RLC_V2} ) set(L2_NR_SRC @@ -1739,7 +1756,7 @@ set(LTE_NR_L2_SRC_UE ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${PDCP_DIR}/pdcp_netlink.c - ${LTE_RLC_SRC} + ${RLC_V2} ) set(NR_L2_SRC_UE @@ -2495,6 +2512,7 @@ add_executable(lte-softmodem ${OPENAIR_TARGETS}/RT/USER/lte-ru.c ${OPENAIR_TARGETS}/RT/USER/ru_control.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/executables/softmodem-common.c ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c @@ -2530,6 +2548,43 @@ target_link_libraries (lte-softmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_L target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES}) target_link_libraries (lte-softmodem ${T_LIB}) + +add_executable(ocp-enb + ${OPENAIR_DIR}/executables/main-ocp.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c + ${OPENAIR_DIR}/executables/softmodem-common.c + ${OPENAIR_DIR}/executables/main-fs6.c + ${OPENAIR_DIR}/executables/transport_split.c + ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c + ${OPENAIR_TARGETS}/COMMON/create_tasks.c + ${OPENAIR_TARGETS}/COMMON/create_tasks_mbms.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + ${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR2_DIR}/RRC/NAS/rb_config.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c + ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/system.c + ${GTPU_need_ITTI} + ${XFORMSINTERFACE_SOURCE} + ${T_SOURCE} + ${CONFIG_SOURCES} + ${SHLIB_LOADER_SOURCES} + ) +add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer) + +target_link_libraries (ocp-enb + -Wl,--start-group + RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB + PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} + -Wl,--end-group z dl) +target_link_libraries (ocp-enb ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) + add_executable(cu_test ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/cu_test.c ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/proto_agent_handler.c @@ -2871,6 +2926,7 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr add_executable(${myExe} ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/system.c ${XFORMS_SOURCE} diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index d5c20ffdc6..88c7a40351 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1177,17 +1177,37 @@ execution nr_pucchsim Test cases. (Test1: Format 0 1-bit ACK miss 106 PRB), - (Test2: Format 0 2-bit ACK miss 106 PRB) + (Test2: Format 0 2-bit ACK miss 106 PRB), + (Test3: Format 0 2-bit ACK miss, 1-bit SR 106 PRB), + (Test4: Format 2 3-bit 106 PRB), + (Test5: Format 2 4-bit 106 PRB), + (Test6: Format 2 5-bit 106 PRB), + (Test7: Format 2 6-bit 106 PRB), + (Test8: Format 2 7-bit 106 PRB), + (Test9: Format 2 8-bit 106 PRB), + (Test10: Format 2 9-bit 106 PRB), + (Test11: Format 2 10-bit 106 PRB), + (Test12: Format 2 11-bit 106 PRB) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/targets/bin/nr_pucchsim.Rel15 - -R 106 -i 1 -P 0 -b 1 -s-7 -n1000 - -R 106 -i 1 -P 0 -b 2 -s-7 -n1000 + -R 106 -i 1 -P 0 -b 1 -s-2 -n1000 + -R 106 -i 1 -P 0 -b 2 -s-2 -n1000 + -R 106 -i 1 -P 0 -b 2 -s-2 -c -n1000 + -R 106 -i 1 -P 2 -b 3 -s0 -n1000 + -R 106 -i 1 -P 2 -b 4 -s0 -n1000 + -R 106 -i 1 -P 2 -b 5 -s1 -n1000 + -R 106 -i 1 -P 2 -b 6 -s2 -n1000 + -R 106 -i 1 -P 2 -b 7 -s3 -n1000 + -R 106 -i 1 -P 2 -b 8 -s4 -n1000 + -R 106 -i 1 -P 2 -b 9 -s5 -n1000 + -R 106 -i 1 -P 2 -b 10 -s6 -n1000 + -R 106 -i 1 -P 2 -b 11 -s6 -n1000 - nr_pucchsim.test1 nr_pucchsim.test2 + nr_pucchsim.test1 nr_pucchsim.test2 nr_pucchsim.test3 nr_pucchsim.test4 nr_pucchsim.test5 nr_pucchsim.test6 nr_pucchsim.test7 nr_pucchsim.test8 nr_pucchsim.test9 nr_pucchsim.test10 nr_pucchsim.test11 nr_pucchsim.test12 PUCCH test OK segmentation fault|assertion|exiting|fatal 3 diff --git a/cmake_targets/nas_sim_tools/CMakeLists.txt b/cmake_targets/nas_sim_tools/CMakeLists.txt index c1a0bb419b..308c71be4c 100644 --- a/cmake_targets/nas_sim_tools/CMakeLists.txt +++ b/cmake_targets/nas_sim_tools/CMakeLists.txt @@ -14,6 +14,7 @@ set(CMAKE_C_FLAGS set(OPENAIR_DIR $ENV{OPENAIR_DIR}) set(OPENAIR3_DIR $ENV{OPENAIR_DIR}/openair3) +include_directories (${OPENAIR_DIR}/openair2/COMMON) set(CONF2UEDATA_LIB_SRC ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_emm.c diff --git a/cmake_targets/phy_simulators/CMakeLists.txt b/cmake_targets/phy_simulators/CMakeLists.txt index b43f7dd389..5f2d34883e 100644 --- a/cmake_targets/phy_simulators/CMakeLists.txt +++ b/cmake_targets/phy_simulators/CMakeLists.txt @@ -1,13 +1,19 @@ cmake_minimum_required(VERSION 2.8) -set(PACKAGE_NAME "unitary_tests_simulators") -set(PHYSIM True) -set(RF_BOARD None) -set(XFORMS True) -set(ENABLE_ITTI True) -set(DEBUG_PHY False) -set(MU_RECIEVER False) -set(NAS_UE False) -set(MESSAGE_CHART_GENERATOR False) -set(RRC_ASN1_VERSION "Rel15") -set(T_TRACER True) -include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt) \ No newline at end of file +set ( CMAKE_BUILD_TYPE ) +set ( CFLAGS_PROCESSOR_USER "" ) +set ( UE_EXPANSION False ) +set ( PRE_SCD_THREAD False ) +set ( UESIM_EXPANSION False ) +set ( ENABLE_VCD_FIFO False ) +set ( RF_BOARD "OAI_USRP") +set ( TRANSP_PRO "None") +set ( PACKAGE_NAME "") +set ( DEADLINE_SCHEDULER "False" ) +set ( CPU_AFFINITY "False" ) +set ( T_TRACER True ) +set ( UE_AUTOTEST_TRACE False ) +set ( UE_DEBUG_TRACE False ) +set ( UE_TIMING_TRACE False ) +set ( USRP_REC_PLAY False ) +set ( SKIP_SHARED_LIB_FLAG False ) +include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 818b1fd79c..8e4ae59a7f 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -217,7 +217,7 @@ install_protobuf_from_source(){ #tar -xzvf protobuf-2.6.1.tar.gz --owner $USER --group $USER --no-same-owner #cd protobuf-2.6.1/ rm -rf /tmp/protobuf-cpp-3.3.0.tar.gz* /tmp/protobuf-3.3.0 - wget https://github.com/google/protobuf/releases/download/v3.3.0/protobuf-cpp-3.3.0.tar.gz + wget --tries=3 --retry-connrefused https://github.com/google/protobuf/releases/download/v3.3.0/protobuf-cpp-3.3.0.tar.gz tar -xzvf protobuf-cpp-3.3.0.tar.gz --owner $USER --group $(groups | cut -d" " -f1) --no-same-owner cd protobuf-3.3.0/ ./configure @@ -353,8 +353,8 @@ install_bladerf_driver_from_source(){ $SUDO ldconfig echo "Downloading FPGA and firmware images" cd /tmp/bladeRF - wget https://www.nuand.com/fx3/bladeRF_fw_latest.img - wget https://www.nuand.com/fpga/hostedx40-latest.rbf + wget --tries=3 --retry-connrefused https://www.nuand.com/fx3/bladeRF_fw_latest.img + wget --tries=3 --retry-connrefused https://www.nuand.com/fpga/hostedx40-latest.rbf sudo mkdir -p /usr/share/Nuand/bladeRF sudo mv bladeRF_fw_latest.img /usr/share/Nuand/bladeRF/bladeRF_fw.img sudo mv hostedx40-latest.rbf /usr/share/Nuand/bladeRF/hostedx40.rbf @@ -567,7 +567,7 @@ check_install_additional_tools (){ echo_info "Installing Netinterfaces package. The logfile for installation is in $log_netiface" ( $SUDO rm -fr /tmp/netifaces-0.10.4.tar.gz /tmp/netifaces - wget -P /tmp https://pypi.python.org/packages/18/fa/dd13d4910aea339c0bb87d2b3838d8fd923c11869b1f6e741dbd0ff3bc00/netifaces-0.10.4.tar.gz + wget --tries=3 --retry-connrefused -P /tmp https://pypi.python.org/packages/18/fa/dd13d4910aea339c0bb87d2b3838d8fd923c11869b1f6e741dbd0ff3bc00/netifaces-0.10.4.tar.gz tar -xzvf /tmp/netifaces-0.10.4.tar.gz -C /tmp cd /tmp/netifaces-0.10.4 $SUDO python setup.py install diff --git a/common/utils/T/tracer/hacks/pilot_timeplot.sh b/common/utils/T/tracer/hacks/pilot_timeplot.sh new file mode 100755 index 0000000000..0d9c4694a6 --- /dev/null +++ b/common/utils/T/tracer/hacks/pilot_timeplot.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# use UP and DOWN arrow keys to scroll the view displayed by timeplot + +while read -n 1 key +do + case "$key" in + 'B' ) + kill -SIGUSR1 `ps aux|grep timeplot|grep -v grep|grep -v sh|tr -s ' ' :|cut -f 2 -d :` + ;; + 'A' ) + kill -SIGUSR2 `ps aux|grep timeplot|grep -v grep|grep -v sh|tr -s ' ' :|cut -f 2 -d :` + ;; + esac +done diff --git a/common/utils/T/tracer/hacks/time_meas.c b/common/utils/T/tracer/hacks/time_meas.c index 6bd2950301..408189cd80 100644 --- a/common/utils/T/tracer/hacks/time_meas.c +++ b/common/utils/T/tracer/hacks/time_meas.c @@ -13,7 +13,8 @@ void usage(void) "options:\n" " -d this option is mandatory\n" " -ip connect to given IP address (default %s)\n" -" -p connect to given port (default %d)\n", +" -p connect to given port (default %d)\n" +" -e event to trace (default VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER)\n", DEFAULT_REMOTE_IP, DEFAULT_REMOTE_PORT ); @@ -47,6 +48,7 @@ int main(int n, char **v) int ev_fun; int start_valid = 0; struct timespec start_time, stop_time, delta_time; + char *name = "VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER"; for (i = 1; i < n; i++) { if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); @@ -55,6 +57,7 @@ int main(int n, char **v) if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; } if (!strcmp(v[i], "-p")) { if (i > n-2) usage(); port = atoi(v[++i]); continue; } + if (!strcmp(v[i], "-e")) { if (i > n-2) usage(); name = v[++i]; continue; } usage(); } @@ -71,10 +74,9 @@ int main(int n, char **v) is_on = calloc(number_of_events, sizeof(int)); if (is_on == NULL) abort(); - on_off(database, "VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER", is_on, 1); + on_off(database, name, is_on, 1); - ev_fun = event_id_from_name(database, - "VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER"); + ev_fun = event_id_from_name(database, name); socket = connect_to(ip, port); diff --git a/common/utils/T/tracer/hacks/timeplot.c b/common/utils/T/tracer/hacks/timeplot.c index 79905d16f9..a1ddb2a1c9 100644 --- a/common/utils/T/tracer/hacks/timeplot.c +++ b/common/utils/T/tracer/hacks/timeplot.c @@ -28,6 +28,7 @@ int bins[50]; #define N 1000 int data[N]; +long start = 100; void plot(void) { @@ -45,7 +46,8 @@ void plot(void) if (data[i] < vmin) vmin = data[i]; if (data[i] > vmax) vmax = data[i]; vavg += data[i]; - int ms2 = data[i]/binsize_ns; + int ms2 = (data[i] - start * 1000)/binsize_ns; + if (ms2 < 0) ms2 = 0; if (ms2 > 49) ms2 = 49; bins[ms2]++; if (bins[ms2] > max) max = bins[ms2]; @@ -55,7 +57,7 @@ void plot(void) GOTO(1,1); for (i = 0; i < 50; i++) { - double binend = (i+1) * binsize_ns / 1000.; + double binend = (i+1) * binsize_ns / 1000. + start; int k; int width = bins[i] * 70 / max; /* force at least width of 1 if some point is there */ @@ -68,11 +70,23 @@ void plot(void) printf("min %d ns max %d ns avg %ld ns\n", vmin, vmax, vavg); } +void up(int x) +{ + start += 5; +} + +void down(int x) +{ + start -= 5; +} + int main(void) { int i; int pos = 0; signal(SIGINT, sig); + signal(SIGUSR1, up); + signal(SIGUSR2, down); RESET(); HIDE_CURSOR(); while (!feof(stdin)) { diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index 89e19074bf..3d4d356dcf 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -1,12 +1,32 @@ /* - Author: Laurent THOMAS, Open Cells - copyleft: OpenAirInterface Software Alliance and it's licence +* 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 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + #include #include #include +extern "C" { #include #include @@ -35,7 +55,6 @@ typedef struct task_list_s { int timer_expired(int fd); task_list_t tasks[TASK_MAX]; -extern "C" { void *pool_buffer_init (void) { return 0; } @@ -86,6 +105,9 @@ extern "C" { temp->ittiMsgHeader.messageId = message_id; temp->ittiMsgHeader.originTaskId = origin_task_id; temp->ittiMsgHeader.ittiMsgSize = size; + temp->ittiMsgHeader.destinationTaskId=TASK_UNKNOWN; + temp->ittiMsgHeader.instance=0; + temp->ittiMsgHeader.lte_time={0}; return temp; //return itti_alloc_new_message_sized(origin_task_id, message_id, messages_info[message_id].size); } diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index ae51f7ff42..9e27ecf358 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -1,7 +1,26 @@ /* - Author: Laurent THOMAS, Open Cells - Copyleft: OpenAirInterface software alliance and it's license +* 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 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* 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 INTERTASK_INTERFACE_H_ #define INTERTASK_INTERFACE_H_ #include @@ -276,7 +295,7 @@ typedef struct { //TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) //TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL) //TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL) - +void * rrc_enb_process_msg(void*); #define FOREACH_TASK(TASK_DEF) \ TASK_DEF(TASK_UNKNOWN, TASK_PRIORITY_MED, 50, NULL, NULL) \ TASK_DEF(TASK_TIMER, TASK_PRIORITY_MED, 10, NULL, NULL) \ diff --git a/common/utils/system.c b/common/utils/system.c index 3a8fe7be3d..1bd5c7d39b 100644 --- a/common/utils/system.c +++ b/common/utils/system.c @@ -243,6 +243,8 @@ void configure_linux(void) { // Set CPU frequency to it's maximum if ( 0 != system("for d in /sys/devices/system/cpu/cpu[0-9]*; do cat $d/cpufreq/cpuinfo_max_freq > $d/cpufreq/scaling_min_freq; done")) - LOG_W(HW,"Can't set cpu frequency\n"); - + LOG_E(HW,"Can't set cpu frequency\n"); + + mlockall(MCL_CURRENT | MCL_FUTURE); + } diff --git a/common/utils/telnetsrv/telnetsrv_enb_measurements.c b/common/utils/telnetsrv/telnetsrv_enb_measurements.c index 9c5c5b675b..8830173e6d 100644 --- a/common/utils/telnetsrv/telnetsrv_enb_measurements.c +++ b/common/utils/telnetsrv/telnetsrv_enb_measurements.c @@ -110,13 +110,13 @@ void measurcmd_display_pdcpcpu(telnet_printfunc_t prnt) { void measurcmd_display_macstats_ue(telnet_printfunc_t prnt) { - UE_list_t *UE_list = &(RC.mac[eNB_id]->UE_list); + UE_info_t *UE_info = &(RC.mac[eNB_id]->UE_info); - for (int UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { - for (int i=0; inumactiveCCs[UE_id]; i++) { - int CC_id = UE_list->ordered_CCids[i][UE_id]; + for (int UE_id=UE_info->list.head; UE_id>=0; UE_id=UE_info->list.next[UE_id]) { + for (int i=0; inumactiveCCs[UE_id]; i++) { + int CC_id = UE_info->ordered_CCids[i][UE_id]; prnt("%s UE %i Id %i CCid %i %s\n",HDR,i,UE_id,CC_id,HDR); - eNB_UE_STATS *macuestatptr = &(UE_list->eNB_UE_stats[CC_id][UE_id]); + eNB_UE_STATS *macuestatptr = &(UE_info->eNB_UE_stats[CC_id][UE_id]); telnet_ltemeasurdef_t statsptr[]=LTEMAC_UEMEASURE; measurcmd_display_measures(prnt, statsptr, sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t)); } @@ -155,7 +155,7 @@ void measurcmd_display_one_rlcstat(telnet_printfunc_t prnt, int UE_id, telnet_lt void measurcmd_display_rlcstats(telnet_printfunc_t prnt) { protocol_ctxt_t ctxt; - UE_list_t *UE_list = &(RC.mac[eNB_id]->UE_list); + UE_info_t *UE_info = &(RC.mac[eNB_id]->UE_info); telnet_ltemeasurdef_t statsptr[]=LTE_RLCMEASURE; int num_rlcmeasure = sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t ); unsigned int *rlcstats = malloc(num_rlcmeasure*sizeof(unsigned int)); @@ -165,9 +165,9 @@ void measurcmd_display_rlcstats(telnet_printfunc_t prnt) { statsptr[i].vptr = rlcstats + i; } - for (int UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { + for (int UE_id=UE_info->list.head; UE_id>=0; UE_id=UE_info->list.next[UE_id]) { #define NB_eNB_INST 1 - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,eNB_id, ENB_FLAG_YES,UE_list->eNB_UE_stats[0][UE_id].crnti, + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,eNB_id, ENB_FLAG_YES,UE_info->eNB_UE_stats[0][UE_id].crnti, eNB->frame,eNB->subframe,eNB_id); measurcmd_display_one_rlcstat(prnt, UE_id, statsptr, num_rlcmeasure, rlcstats, "DCCH", &ctxt, SRB_FLAG_YES, DCCH); measurcmd_display_one_rlcstat(prnt, UE_id, statsptr, num_rlcmeasure, rlcstats, "DTCH", &ctxt, SRB_FLAG_NO, DTCH-2); diff --git a/common/utils/threadPool/measurement_display.c b/common/utils/threadPool/measurement_display.c index 8f6e2c239a..0f5a3e0f69 100644 --- a/common/utils/threadPool/measurement_display.c +++ b/common/utils/threadPool/measurement_display.c @@ -1,7 +1,26 @@ /* - Author: Laurent THOMAS, Open Cells - copyleft: OpenAirInterface Software Alliance and it's licence +* 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 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + #include #include "thread-pool.h" diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index dd3d16d717..cbb2dbe3d9 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -1,8 +1,27 @@ /* - Author: Laurent THOMAS, Open Cells - copyleft: OpenAirInterface Software Alliance and it's licence +* 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 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* 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 */ + #define _GNU_SOURCE #include #include diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index 9a2681a828..0ed8715811 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -1,8 +1,27 @@ /* - Author: Laurent THOMAS, Open Cells - copyleft: OpenAirInterface Software Alliance and it's licence +* 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 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* 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 THREAD_POOL_H #define THREAD_POOL_H #include @@ -217,11 +236,11 @@ static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { notifiedFIFO_elt_t *msg= pullNotifiedFIFO(responseFifo); - + AssertFatal(t->traceFd, "Thread pool used while not initialized"); if (t->measurePerf) msg->returnTime=rdtsc(); - if (t->traceFd >= 0) + if (t->traceFd > 0) if(write(t->traceFd, msg, sizeof(*msg))); return msg; @@ -229,7 +248,7 @@ static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_ static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { notifiedFIFO_elt_t *msg= pollNotifiedFIFO(responseFifo); - + AssertFatal(t->traceFd, "Thread pool used while not initialized"); if (msg == NULL) return NULL; diff --git a/doc/L2NFAPI.md b/doc/L2NFAPI.md index 4dcaaef3bc..137e4847e4 100644 --- a/doc/L2NFAPI.md +++ b/doc/L2NFAPI.md @@ -14,19 +14,24 @@ This simulator allows to test L2 and above Layers using the nFAPI interface. +The UE executable is able to "simulate" multiple UEs in order to stimulate the scheduler in the eNB. + **This simulator is available starting the `v1.0.0` release on the `master` branch.** -Currently the only validated deployment by CI and developers is *with S1 interface and eNB / UEs are on the same machine*. - -Others deployments will be supported later after bug fixes and validation in the CI process. - -1. [With S1 -- eNB and UE on same machine](L2NFAPI_S1.md) - - +Currently the Continuous Integration process is validating this simulator the following way: +* the LTE modem executable is run on one host (in our CI deployment it is a **Xenial Virtual Machine**) +* the UE(s) modem executable is run on another host (in our CI deployment it is also a **Xenial Virtual Machine**) +* We are testing: + * in S1 mode (ie we are connected to a 3rd-party EPC) + * in noS1 mode (no need for an EPC) +Normally it should be fine to run both executables on the same host using the `loopback` interface to communicate. **But we are not guaranting it** +1. [With S1 -- eNB and UE on 2 hosts](L2NFAPI_S1.md) +2. [No S1 -- eNB and UE on 2 hosts](L2NFAPI_NOS1.md) +---- [oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) diff --git a/doc/L2NFAPI_NOS1.md b/doc/L2NFAPI_NOS1.md new file mode 100644 index 0000000000..bb4c32ec08 --- /dev/null +++ b/doc/L2NFAPI_NOS1.md @@ -0,0 +1,349 @@ + + + + + +
+ + + + + + L2 nFAPI Simulator (no S1 Mode / 2-host deployment) +
+ +## Table of Contents ## + +1. [Environment](#1-environment) +2. [Retrieve the OAI eNB-UE source code](#2-retrieve-the-oai-enb-ue-source-code) +3. [Setup of the USIM information in UE folder](#3-setup-of-the-usim-information-in-ue-folder) +4. [Setup of the Configuration files](#4-setup-of-the-configuration-files) + 1. [The eNB Configuration file](#41-the-enb-configuration-file) + 2. [The UE Configuration file](#42-the-ue-configuration-file) +5. [Build OAI UE and eNodeB](#5-build-oai-ue-and-enodeb) +6. [Start the eNB](#6-start-the-enb) +7. [Start the UE](#7-start-the-ue) +8. [Test with ping](#8-test-with-ping) +9. [Limitations](#9-limitations) + +# 1. Environment # + +You may not have access to an EPC or you don't want to hassle to deploy one. + +2 servers are used in this deployment. You can use Virtual Machines instead of each server; like it is done in the CI process. + +* Machine B contains the OAI eNB executable (`lte-softmodem`) +* Machine C contains the OAI UE(s) executable (`lte-uesoftmodem`) + +Example of L2 nFAPI Simulator testing environment: + + + +Note that the IP addresses are indicative and need to be adapted to your environment. + +# 2. Retrieve the OAI eNB-UE source code # + +At the time of writing, the tag used in the `develop` branch to do this documentation was `2020.w16`. + +The tutorial should be valid for the `master` branch tags such as `v1.2.0` or `v1.2.1`. But you may face issues that could be fixed in newer `develop` tags. + +Please try to use the same commit ID on both eNB/UE hosts. + +```bash +$ ssh sudousername@machineB +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git enb_folder +cd enb_folder +git checkout develop +``` + +```bash +$ ssh sudousername@machineC +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ue_folder +cd ue_folder +git checkout develop +``` + +# 3. Setup of the USIM information in UE folder # + +```bash +$ ssh sudousername@machineC +cd ue_folder +# Edit openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf with your preferred editor +``` + +Edit the USIM information within this file in order to match the HSS database. They **HAVE TO** match: + +* PLMN+MSIN and IMSI of users table of HSS database **SHALL** be the same. +* OPC of this file and OPC of users table of HSS database **SHALL** be the same. +* USIM_API_K of this file and the key of users table of HSS database **SHALL** be the same. + +When testing multiple UEs, it is necessary to add other UEs information like described below for 2 Users. Only UE0 (first UE) information is written in the original file. + +``` +UE0: +{ + USER: { + IMEI="356113022094149"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; + + SIM: { + MSIN="0000000001"; // <-- Modify here + USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; + OPC="e734f8734007d6c5ce7a0508809e7e9c"; + MSISDN="33611123456"; + }; +... +}; +// Copy the UE0 and edit +UE1: // <- Edit here +{ + USER: { + IMEI="356113022094149"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; + + SIM: { + MSIN="0000000002"; // <-- Modify here + USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; + OPC="e734f8734007d6c5ce7a0508809e7e9c"; + MSISDN="33611123456"; + }; +... +}; +``` + +You can repeat the operation for as many users you want to test with. + +# 4. Setup of the Configuration files # + +**CAUTION: both proposed configuration files resides in the ci-scripts realm. You can copy them but you CANNOT push any modification on these 2 files as part of an MR without informing the CI team.** + +## 4.1. The eNB Configuration file ## + +```bash +$ ssh sudousername@machineB +cd enb_folder +# Edit ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf with your preferred editor +``` + +First verify the nFAPI interface setup on the physical ethernet interface of machineB and put the proper IP addresses for both hosts. + +``` +MACRLCs = ( + { + num_cc = 1; + local_s_if_name = "ens3"; // <-- HERE + remote_s_address = "192.168.122.169"; // <-- HERE + local_s_address = "192.168.122.31"; // <-- HERE + local_s_portc = 50001; + remote_s_portc = 50000; + local_s_portd = 50011; + remote_s_portd = 50010; + tr_s_preference = "nfapi"; + tr_n_preference = "local_RRC"; + } +); +``` + +If you are testing more than 16 UEs, a proper setting on the RUs is necessary. **Note that this part is NOT present in the original configuration file**. + +``` +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 20 + att_rx = 0; + bands = [38]; + max_pdschReferenceSignalPower = -23; + max_rxgain = 116; + eNB_instances = [0]; + } +); +``` + +Last, the S1 interface shall be properly set. + +``` + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; // replace with 192.168.122.195 + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "ens3"; // replace with the proper interface name + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 + ENB_INTERFACE_NAME_FOR_S1U = "ens3"; // replace with the proper interface name + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + + }; +``` + +## 4.2. The UE Configuration file ## + +```bash +$ ssh sudousername@machineB +cd ue_folder +# Edit ci-scripts/conf_files/ue.nfapi.conf with your preferred editor +``` + +Verify the nFAPI interface setup on the loopback interface. + +``` +L1s = ( + { + num_cc = 1; + tr_n_preference = "nfapi"; + local_n_if_name = "ens3"; // <- HERE + remote_n_address = "192.168.122.31"; // <- HERE + local_n_address = "192.168.122.169"; // <- HERE + local_n_portc = 50000; + remote_n_portc = 50001; + local_n_portd = 50010; + remote_n_portd = 50011; + } +); +``` + +# 5. Build OAI UE and eNodeB # + +See [Build documentation](./BUILD.md). + +# 6. Start the eNB # + +In the first terminal (the one you used to build the eNB): + +```bash +$ ssh sudousername@machineB +cd enb_folder/cmake_targets +sudo -E ./ran_build/build/lte-softmodem -O ../ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf --noS1 > enb.log 2>&1 +sleep 10 +ifconfig +ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX + inet addr:192.168.122.31 Bcast:192.168.122.255 Mask:255.255.255.0 +.... +oaitun_enb1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.1 P-t-P:192.172.0.2 Mask:255.255.255.0 +.... +``` + +If you don't use redirection, you can test but many logs are printed on the console and this may affect performance of the L2-nFAPI simulator. + +We do recommend the redirection in steady mode once your setup is correct. + +# 7. Start the UE # + +In the second terminal (the one you used to build the UE): + +```bash +$ ssh sudousername@machineC +cd ue_folder/cmake_targets +# Test 64 UEs, 1 thread in FDD mode +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 > ue.log 2>&1 +# Test 64 UEs, 1 thread in TDD mode +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 -T 1 > ue.log 2>&1 +# The "-T 1" option means TDD config +``` + +- The number of UEs can set by using `--num-ues` option and the maximum UE number is 255 (with the `--mu*` options, otherwise 16). +- The number of threads can set with the `--nums-ue-thread`. This number **SHALL NOT** be greater than the number of UEs. + * At the time of writing, it seems to be enough to run on a single thread. +- The `--nokrnmod 1` option makes use of the preferred and supported tunnel interface. +- How many UE that can be tested depends on hardware (server , PC, etc) performance in your environment. + +For example, running with 4 UEs: + +```bash +$ ssh sudousername@machineC +cd ue_folder/cmake_targets +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 > ue.log 2>&1 +sleep 10 +ifconfig +ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX + inet addr:192.168.122.169 Bcast:192.168.122.255 Mask:255.255.255.0 +.... +oaitun_ue1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.2 P-t-P:192.172.0.2 Mask:255.255.255.0 +.... +oaitun_ue2 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.3 P-t-P:192.172.0.3 Mask:255.255.255.0 +.... +oaitun_ue3 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.4 P-t-P:192.172.0.4 Mask:255.255.255.0 +.... +oaitun_ue4 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.5 P-t-P:192.172.0.5 Mask:255.255.255.0 +.... +oaitun_uem1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.2.2 P-t-P:10.0.2.2 Mask:255.255.255.0 +.... +.... +``` + +Having the 4 oaitun_ue tunnel interfaces up and with an allocated address means the connection with EPC went alright. + +# 8. Test with ping # + +In a third terminal, after around 10 seconds, the UE(s) shall be connected to the eNB: Check with ifconfig + +```bash +$ ssh sudousername@machineB +# Ping UE1 IP address based on the EPC pool used: in this example: +ping -I oaitun_enb1 -c 20 10.0.1.2 +# Ping UE4 IP address based on the EPC pool used: in this example: +ping -I oaitun_enb1 -c 20 10.0.1.5 +``` + +Ping from the UE side: + +```bash +$ ssh sudousername@machineC +ping -I oaitun_ue1 -c 20 10.0.1.1 +ping -I oaitun_ue3 -c 20 10.0.1.1 +``` + +iperf operations can also be performed. + +DL traffic: + +```bash +$ ssh sudousername@machineC +iperf -B 10.0.1.2 -u -s -i 1 -fm -p 5002 +$ ssh sudousername@machineB +iperf -c 10.0.1.2 -u -t 30 -b 3M -i 1 -fm -B 10.0.1.1 -p 5002 +``` + +UL traffic: + +```bash +$ ssh sudousername@machineB +iperf -B 10.0.1.1 -u -s -i 1 -fm -p 5002 +$ ssh sudousername@machineC +iperf -c 10.0.1.1 -u -t 30 -b 2M -i 1 -fm -B 10.0.1.2 -p 5002 +``` + +# 9. Limitations # + + +---- + +[oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) + +[oai softmodem features](FEATURE_SET.md) + +[oai softmodem build procedure](BUILD.md) + +[L2 nfapi simulator](L2NFAPI.md) diff --git a/doc/L2NFAPI_S1.md b/doc/L2NFAPI_S1.md index b9156e9379..9fd6d51818 100644 --- a/doc/L2NFAPI_S1.md +++ b/doc/L2NFAPI_S1.md @@ -7,7 +7,7 @@ - L2 nFAPI Simulator (with S1 / same machine deployment) + L2 nFAPI Simulator (with S1 / 2-host deployment) @@ -21,25 +21,24 @@ 5. [Setup of the Configuration files](#5-setup-of-the-configuration-files) 1. [The eNB Configuration file](#51-the-enb-configuration-file) 2. [The UE Configuration file](#52-the-ue-configuration-file) -6. [Bring Up a second loopback interface](#6-bring-up-a-second-loopback-interface) -7. [Build the eNB](#7-build-the-enb) -8. [Build the UE](#8-build-the-ue) -9. [Initialize the NAS UE Layer](#9-initialize-the-nas-ue-layer) -10. [Start the eNB](#10-start-the-enb) -11. [Start the UE](#11-start-the-ue) -12. [Test with ping](#12-test-with-ping) -13. [Limitations](#13-limitations) +6. [Build OAI UE and eNodeB](#6-build-oai-ue-and-enodeb) +7. [Start EPC](#7-start-epc) +8. [Start the eNB](#8-start-the-enb) +9. [Start the UE](#9-start-the-ue) +10. [Test with ping](#10-test-with-ping) +11. [Limitations](#11-limitations) # 1. Environment # -2 servers are used in this deployment. You can use Virtual Machines instead of each server; like it is done in the CI process. +3 servers are used in this deployment. You can use Virtual Machines instead of each server; like it is done in the CI process. * Machine A contains the EPC. -* Machine B contains the OAI eNB and the OAI UE(s) +* Machine B contains the OAI eNB executable (`lte-softmodem`) +* Machine C contains the OAI UE(s) executable (`lte-uesoftmodem`) Example of L2 nFAPI Simulator testing environment: - + Note that the IP addresses are indicative and need to be adapted to your environment. @@ -47,26 +46,35 @@ Note that the IP addresses are indicative and need to be adapted to your environ Create the environment for the EPC and register all **USIM** information into the **HSS** database. -If you are using OAI-EPC ([see on GitHub](https://github.com/OPENAIRINTERFACE/openair-cn)), build **HSS/MME/SPGW** and create config files. +If you are using OAI-EPC ([see on GitHub](https://github.com/OPENAIRINTERFACE/openair-epc-fed)), build **HSS/MME/SPGW** and create config files. # 3. Retrieve the OAI eNB-UE source code # -The eNB and the UE executables will compiled into 2 separate folders on the same machine `B`. +At the time of writing, the tag used in the `develop` branch to do this documentation was `2020.w16`. + +The tutorial should be valid for the `master` branch tags such as `v1.2.0` or `v1.2.1`. But you may face issues that could be fixed in newer `develop` tags. + +Please try to use the same commit ID on both eNB/UE hosts. ```bash $ ssh sudousername@machineB -$ git clone https://gitlab.eurecom.fr/oai/openairinterface5g/ enb_folder -$ cd enb_folder -$ git checkout -f v1.0.0 -$ cd .. -$ cp -Rf enb_folder ue_folder +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git enb_folder +cd enb_folder +git checkout develop +``` + +```bash +$ ssh sudousername@machineC +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ue_folder +cd ue_folder +git checkout develop ``` # 4. Setup of the USIM information in UE folder # ```bash -$ ssh sudousername@machineB -$ cd ue_folder +$ ssh sudousername@machineC +cd ue_folder # Edit openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf with your preferred editor ``` @@ -126,19 +134,19 @@ You can repeat the operation for as many users you want to test with. ```bash $ ssh sudousername@machineB -$ cd enb_folder +cd enb_folder # Edit ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf with your preferred editor ``` -First verify the nFAPI interface setup on the 2nd loopback interface. +First verify the nFAPI interface setup on the physical ethernet interface of machineB and put the proper IP addresses for both hosts. ``` MACRLCs = ( { num_cc = 1; - local_s_if_name = "lo:"; // <-- HERE - remote_s_address = "127.0.0.1"; // <-- HERE - local_s_address = "127.0.0.2"; // <-- HERE + local_s_if_name = "ens3"; // <-- HERE + remote_s_address = "192.168.122.169"; // <-- HERE + local_s_address = "192.168.122.31"; // <-- HERE local_s_portc = 50001; remote_s_portc = 50000; local_s_portd = 50011; @@ -171,7 +179,7 @@ Last, the S1 interface shall be properly set. ``` ////////// MME parameters: - mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; // replace with 192.168.10.20 + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; // replace with 192.168.122.195 ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -181,11 +189,11 @@ Last, the S1 interface shall be properly set. NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "ens3"; // replace with the proper interface name - ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; // replace with 192.168.10.10 + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 ENB_INTERFACE_NAME_FOR_S1U = "ens3"; // replace with the proper interface name - ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; // replace with 192.168.10.10 + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 ENB_PORT_FOR_S1U = 2152; # Spec 2152 - ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; // replace with 192.168.10.10 + ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 ENB_PORT_FOR_X2C = 36422; # Spec 36422 }; @@ -195,7 +203,7 @@ Last, the S1 interface shall be properly set. ```bash $ ssh sudousername@machineB -$ cd ue_folder +cd ue_folder # Edit ci-scripts/conf_files/ue.nfapi.conf with your preferred editor ``` @@ -206,9 +214,9 @@ L1s = ( { num_cc = 1; tr_n_preference = "nfapi"; - local_n_if_name = "lo"; // <- HERE - remote_n_address = "127.0.0.2"; // <- HERE - local_n_address = "127.0.0.1"; // <- HERE + local_n_if_name = "ens3"; // <- HERE + remote_n_address = "192.168.122.31"; // <- HERE + local_n_address = "192.168.122.169"; // <- HERE local_n_portc = 50000; remote_n_portc = 50001; local_n_portd = 50010; @@ -217,20 +225,11 @@ L1s = ( ); ``` -# 6. Bring Up a second loopback interface # +# 6. Build OAI UE and eNodeB # -A second loopback interface is used to connect the eNB and the UEs. +See [Build documentation](./BUILD.md). -```bash -$ ssh sudousername@machineB -$ sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up -``` - -# 7. [Build OAI UE and eNodeB](BUILD.md) # - - - -# 8. Initialize the NAS UE Layer # +# 7. Start EPC # Start the EPC on machine `A`. @@ -239,61 +238,89 @@ $ ssh sudousername@machineA # Start the EPC ``` -# 9. Start the eNB # +# 8. Start the eNB # In the first terminal (the one you used to build the eNB): ```bash $ ssh sudousername@machineB -$ cd enb_folder/cmake_targets -$ sudo -E ./ran_build/build/lte-softmodem -O ../ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf > enb.log 2>&1 +cd enb_folder/cmake_targets +sudo -E ./ran_build/build/lte-softmodem -O ../ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf > enb.log 2>&1 ``` If you don't use redirection, you can test but many logs are printed on the console and this may affect performance of the L2-nFAPI simulator. We do recommend the redirection in steady mode once your setup is correct. -# 10. Start the UE # +# 9. Start the UE # In the second terminal (the one you used to build the UE): ```bash -$ ssh sudousername@machineB -$ cd ue_folder/cmake_targets -# Test 64 UEs, 64 threads in FDD mode -$ sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums-ue-thread 64 > ue.log 2>&1 -# Test 64 UEs, 64 threads in TDD mode -$ sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums-ue-thread 64 -T 1 > ue.log 2>&1 +$ ssh sudousername@machineC +cd ue_folder/cmake_targets +# Test 64 UEs, 1 thread in FDD mode +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 > ue.log 2>&1 +# Test 64 UEs, 1 thread in TDD mode +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 -T 1 > ue.log 2>&1 # The "-T 1" option means TDD config ``` - The number of UEs can set by using `--num-ues` option and the maximum UE number is 255 (with the `--mu*` options, otherwise 16). -- The umber of threads can set with the `--nums-ue-thread`. This number **SHALL NOT** be greater than the number of UEs. +- The number of threads can set with the `--nums-ue-thread`. This number **SHALL NOT** be greater than the number of UEs. + * At the time of writing, it seems to be enough to run on a single thread. +- The `--nokrnmod 1` option makes use of the preferred and supported tunnel interface. - How many UE that can be tested depends on hardware (server , PC, etc) performance in your environment. -# 11. Test with ping # +For example, running with 4 UEs: -In a third terminal, after around 10 seconds, the UE(s) shall be connected to the eNB: +```bash +$ ssh sudousername@machineC +cd ue_folder/cmake_targets +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 > ue.log 2>&1 +sleep 10 +ifconfig +ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX + inet addr:192.168.122.169 Bcast:192.168.122.255 Mask:255.255.255.0 +.... +oaitun_ue1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:192.172.0.2 P-t-P:192.172.0.2 Mask:255.255.255.0 +.... +oaitun_ue2 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:192.172.0.3 P-t-P:192.172.0.3 Mask:255.255.255.0 +.... +oaitun_ue3 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:192.172.0.4 P-t-P:192.172.0.4 Mask:255.255.255.0 +.... +oaitun_ue4 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:192.172.0.5 P-t-P:192.172.0.5 Mask:255.255.255.0 +.... +oaitun_uem1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.2.2 P-t-P:10.0.2.2 Mask:255.255.255.0 +.... +.... +``` + +Having the 4 oaitun_ue tunnel interfaces up and with an allocated address means the connection with EPC went alright. + +# 10. Test with ping # + +In a third terminal, after around 10 seconds, the UE(s) shall be connected to the eNB: Check with ifconfig ```bash $ ssh sudousername@machineA -# Ping UE0 IP address based on the EPC pool used: in this example: -$ ping -c 20 192.168.200.2 # Ping UE1 IP address based on the EPC pool used: in this example: -$ ping -c 20 192.168.200.4 +$ ping -c 20 192.172.0.2 +# Ping UE4 IP address based on the EPC pool used: in this example: +$ ping -c 20 192.172.0.5 ``` -# 12. Limitations # - -Testing on the CI process is currently limited at time of writing. Improvements will be made soon. - - - - - +iperf operations can also be performed. +# 11. Limitations # +---- [oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) diff --git a/doc/SystemX-tutorial-design.md b/doc/SystemX-tutorial-design.md new file mode 100644 index 0000000000..3e4496f7de --- /dev/null +++ b/doc/SystemX-tutorial-design.md @@ -0,0 +1,336 @@ +# OpenAirInterface for SystemX + +# Terminology + +****This document use the 5G terminology**** + +**Central Unit (CU):** It is a logical node that includes the gNB +functions like Transfer of user data, Mobility control, Radio access +network sharing, Positioning, Session Management etc., except those +functions allocated exclusively to the DU. CU controls the operation of +DUs over front-haul (Fs) interface. A central unit (CU) may also be +known as BBU/REC/RCC/C-RAN/V-RAN/VNF + +**Distributed Unit (DU):** This logical node includes a subset of the +gNB functions, depending on the functional split option. Its operation +is controlled by the CU. Distributed Unit (DU) also known with other +names like RRH/RRU/RE/RU/PNF. + +In OpenAir code, the terminology is often RU and BBU. + +# OpenAirUsage + +## EPC and general environment + +### OAI EPC + +Use the stable OAI EPC, that can run in one machine (VM or standalone) + +Draft description: + + +## Standalone 4G + +EPC+eNB on one machine, the UE can be commercial or OAI UE. + +### USRP B210 + +Main current issue: traffic is good only on coaxial link between UE and +eNB (probably power management issue). + +### Simulated RF + +Running eNB+UE both OAI can be done over a virtual RF link. + +The UE current status is that threads synchronization is implicit in +some cases. As the RF simulator is very quick, a “sleep()” is required +in the UE main loop + +(line 1744, targets/RT/USER/lte-ue.c). + +Running also the UE in the same machine is possible with simulated RF. + +Running in same machine is simpler, offers about infinite speed for +virtual RF samples transmission. + +A specific configuration is required because the EPC Sgi interface has +the same IP tunnel end point as the UE. + +So, we have to create a network namespace for the UE and to route data +in/out of the namespace. + +```bash +ip netns delete aNameSpace 2> /dev/null + +ip link delete v-eth1 2> /dev/null + +ip netns add aNameSpace + +ip link add v-eth1 type veth peer name v-peer1 + +ip link set v-peer1 netns aNameSpace + +ip addr add 10.200.1.1/24 dev v-eth1 + +ip link set v-eth1 up + +iptables -t nat -A POSTROUTING -s 10.200.1.0/255.255.255.0 -o enp0s31f6 \ +-j MASQUERADE + +iptables -A FORWARD -i enp0s31f6 -o v-eth1 -j ACCEPT + +iptables -A FORWARD -o enp0s31f6 -i v-eth1 -j ACCEPT + +ip netns exec aNameSpace ip link set dev lo up + +ip netns exec aNameSpace ip addr add 10.200.1.2/24 dev v-peer1 + +ip netns exec aNameSpace ip link set v-peer1 up + +ip netns exec aNameSpace bash +``` + +After the last command, the Linux shell is in the new namespace, ready +to run the UE. + +To make user plan traffic, the traffic generator has to run in the same +namespace + +```bash +ip netns exec aNameSpace bash +``` + +The traffic genenrator has to specify the interface: + +```bash +route add default oaitun_ue1 +``` + +or specify the outgoing route in the traffic generator (like option “-I” +in ping command). + +## Split 6 DL 4G + +The contract describes to reuse the uplink existing if4p5 and to develop +is this work the downlink “functional split 6”. + +The customer required after signature to develop also the uplink +functional split 6. This is accepted, as long as the whole work is +research with no delivery completeness warranty. + +### Simulation + +To be able to verify the new features and to help in all future +developments, Open Cells added and improved the Rf board simulator +during this contract. + +We added the channel modeling simulation, that offer to simulate various +3GPP defined channels. + +### Main loop + +The main log is in RF simulator is in + + `targets/RT/USER/lte-ru.c and targets/RT/USER/lte-enb.c` + +As this piece of SW is very complex and doesn’t meet our goals +(functional split 6), a cleaned version replaces these 2 files in +executables/ocp-main.c (openair1/SCHED/prach\_procedures.c is also +replaced by this new file as it only launching the RACH actual work in a +way not compatible with our FS6). + +The main loop cadences the I/Q samples reception, signal processing and +I/Q samples sending. + +The main loop uses extensively function pointers to call the right +processing function depending on the split case. + +A lot of OAI reduntant global variables contains the same semantic data: time,frame, subframe. +The reworked main loop take care of a uniq variable that comes directly from harware: RF board sampling number. + +To use OAI, we need to set all OAI variables that derivates from this timestamp value. The function setAllfromTS() implements this. + +### Splitted main level + +When FS6 is actived, a main loop for DU (du_fs6()) a main loop for CU case replaces the uniq eNB main loop. + +Each of these main loops calls initialization of OAI LTE data and the FS6 transport layer initialization. + +Then, it runs a infinite loop on: set time, call UL and DL. The time comes from the RF board, so the DU sends the time to the CU. + +This is enough for RF board dialog, but the FS6 is higher in SW layers, +we need to cut higher functions inside downlink and uplink procedures. + +As much as possible, the FS6 code is in the directory OPENAIR_DIR/executables. When a given OAI piece of code is small or need complex changes, it is reworked in the file fs6-main.c. The functions naming keeps the OAI function name, adding suffix _fromsplit() or _tosplit(). + +When this organization would lead to large code copy, it is better to insert modifications in OAI code. This is done in two files: + +- openair1/SCHED/phy_procedures_lte_eNb.c: to send signaling channels computation results + - the function sendFs6Ulharq() centralizes all signaling channels forwarding to CU +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c: to deal with FS6 user plane split + - sendFs6Ul() is used once to forward user plane to CU + + +### DownLink + +The main procedure is phy\_procedures\_eNB\_TX() + +This is building the common channels (beacon, multi-UE signaling). + +The FS6 split breaks this function into pieces: + +* The multi-UE signals, built by common\_signal\_procedures(), + subframe2harq\_pid(), generate\_dci\_top(), subframe2harq\_pid() + * These functions run in the DU, nevertheless all context has to be sent + (it is also needed partially for UL spitting) + * Run in the DU also to meet the requirement of pushing + in DU the data encoded with large redundancy (>3 redundancy) + +* the per UE data: pdsch\_procedures() needs further splitting: + + * dlsch\_encoding\_all() that makes the encoding: turbo code + and lte\_rate\_matching\_turbo() that will be in the DU (some + unlikely cases can reach redundancy up to x3, when MCS is very + low (negative SINR cases)). + + * dlsch\_encoding() output needs to be transmitted between the + DU and the CU for functional split 6. + * dlsch\_scrambling() that will go in the DU + * dlsch\_modulation() that will go in the DU + + The du user plane data is made of expanded bit in OAI at FS6 split level. 1 pair of functions compact back these bits into 8bits/byte before sending data and expand it again in the DU data reception (functions: fs6Dl(un)pack()). + +### Uplink + +The uplink require configuration that is part of the DL transmission. + +It interprets the signalling to extract the RACH and the per UE data +channels. + +Ocp-main.c:rxtx() calls directly the entry procedure +phy\_procedures\_eNB\_uespec\_RX() calls: + +* rx\_ulsch() that demodulate and extract soft bits per UE. + + * This function runs in the DU + * the output data will be processes in the DU, so it needs to be + transmitted to the DU +* ulsch\_decoding() that do lte\_rate\_matching\_turbo\_rx() + sub\_block\_deinterleaving\_turbo() + then turbo decode that is in the CU +* fill\_ulsch\_cqi\_indication() fill\_crc\_indication() , fill\_rx\_indication() + * DU performs the signal processing of each channel data, prepare and sent to the CU the computed result + +* Random access channel detection runs in the DU + * the DU reports to the CU only the detected temprary identifier for RACH response + + +### signaling data in each direction (UL and DL) + + +* each LTE channel needs to be propagated between CU and DU + * the simplest are the almost static data such as PSS/SSS, that need only static eNB parameters and primary information (frame numbering) + * all the other channels require data transmission CU to DU and DU to CU + * the general design push all the low level processing for these channels in the DU + * the CU interface transports only signal processing results (UL) or configuration to create the RF signal (DL case) +* HARQ is detected in the DU, then only the ACK or NACK is reported to CU + +* the CU have to control the power and MCS (modulation and coding scheme) + * the DU performs the signal processing and report only the decoded data like the CQI + * as the DU performas the modulation, scrambling and puncturing, each data packet is associated with the LTE parameters required for these features + * in DL, the CU associates the control parameters and the user plane data + * in UL, the CU sends upfront the scheduled UL data to the DU. So, the DU have the required knowledge to decode the next subframes in time. + +### UDP transport layer + +A general UDP transport layer is in executables/transport\_split.c + +Linux offers a UDP socket builtin timeout, that we use. + +In and out buffers are memory zones that contains compacted +(concatenated) UDP chunks. + +For output, sendSubFrame() sends each UDP chunk + +For input, receiveSubFrame() collects all UDP chunks for a group (a +subframe in OAI LTE case). It returns in the following cases: + +- all chunks are received +- a timeout expired +- a chunk from the next subframe already arrived + +### Functional split 6 usage + +The ocp cleaned main hale to be used: run ocp-softmodem instead of +lte-softmodem. + +The functionality and parameters is the same, enhanced with FS6 mode. + +The end line option “--split73” enables the fs6 (also called split 7.3) mode and decided to be cu or du. + +Example: + +```bash +./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 cu:127.0.0.1 +``` + +Run the CU init of the split 6 eNB, that will call du on 127.0.0.1 address + +```bash +./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 du:127.0.0.1 +``` + +will run the du, calling the cu on 127.0.0.1 + +If the CU and the DU are not on the same machine, the remote address of each side need to be specified as per this example + +```bash +./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 du:192.168.1.55 +``` + +runs the functional split 6 DU + +```bash +./lte-uesoftmodem -C 2685000000 -r 50 --rfsim --rfsimulator.serveraddr 192.168.1.1 -d +``` + +Runs the UE (to have the UE signal scope, compile it with make uescope) + +CU+DU+UE can run with option `--noS1` to avoid to use a EPC and/or with `--rfsim` to simulate RF board + + +## 5G and F1 + +Today 5G achievement is limited to physical layer. + +The available modulation is 40MHz, that require one X310 or N300 for the +gNB and a X310 or N300 for the nrUE. + +### Usage with X310 + +Linux configuration: + + +We included most of this configuration included in OAI source code. + +Remain to set the NIC (network interface card) MTU to 9000 (jumbo +frames). + +### Running 5G + +Usage with RFsimulator: + +**gNB** + +```bash +sudo RFSIMULATOR=server ./nr-softmodem -O \ +../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf \ +--parallel-config PARALLEL\_SINGLE\_THREAD +``` + +**nrUE** + +```bash +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C \ +3510000000 -d +``` diff --git a/doc/images/L2-sim-S1-3-host-deployment.png b/doc/images/L2-sim-S1-3-host-deployment.png new file mode 100644 index 0000000000..4049ebd7a8 Binary files /dev/null and b/doc/images/L2-sim-S1-3-host-deployment.png differ diff --git a/doc/images/L2-sim-noS1-2-host-deployment.png b/doc/images/L2-sim-noS1-2-host-deployment.png new file mode 100644 index 0000000000..02d29b7b3c Binary files /dev/null and b/doc/images/L2-sim-noS1-2-host-deployment.png differ diff --git a/executables/main-fs6.c b/executables/main-fs6.c new file mode 100644 index 0000000000..45a6271887 --- /dev/null +++ b/executables/main-fs6.c @@ -0,0 +1,1602 @@ +/* +* 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 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FS6_BUF_SIZE 1000*1000 +static UDPsock_t sockFS6; + +int sum(uint8_t *b, int s) { + int sum=0; + + for (int i=0; i < s; i++) + sum+=b[i]; + + return sum; +} + +static inline int cmpintRev(const void *a, const void *b) { + uint64_t *aa=(uint64_t *)a; + uint64_t *bb=(uint64_t *)b; + return (int)(*bb-*aa); +} + +static inline void printMeas2(char *txt, Meas *M, int period, bool MaxMin) { + if (M->iterations%period == 0 ) { + char txt2[512]; + sprintf(txt2,"%s avg=%" PRIu64 " iterations=%" PRIu64 " %s=%" + PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 "\n", + txt, + M->sum/M->iterations, + M->iterations, + MaxMin?"max":"min", + M->maxArray[1],M->maxArray[2], M->maxArray[3],M->maxArray[4], M->maxArray[5], + M->maxArray[6],M->maxArray[7], M->maxArray[8],M->maxArray[9],M->maxArray[10]); +#if T_TRACER + LOG_W(PHY,"%s",txt2); +#else + printf("%s",txt2); +#endif + } +} + +static inline void updateTimesReset(uint64_t start, Meas *M, int period, bool MaxMin, char *txt) { + if (start!=0) { + uint64_t end=rdtsc(); + long long diff=(end-start)/(cpuf*1000); + M->maxArray[0]=diff; + M->sum+=diff; + M->iterations++; + + if ( MaxMin) + qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); + else + qsort(M->maxArray, 11, sizeof(uint64_t), cmpintRev); + + printMeas2(txt,M,period, MaxMin); + + if (M->iterations%period == 0 ) { + bzero(M,sizeof(*M)); + + if (!MaxMin) + for (int i=0; i<11; i++) + M->maxArray[i]=INT_MAX; + } + } +} + +static inline void measTransportTime(uint64_t DuSend, uint64_t CuMicroSec, Meas *M, int period, bool MaxMin, char *txt) { + if (DuSend!=0) { + uint64_t end=rdtsc(); + long long diff=(end-DuSend)/(cpuf*1000)-CuMicroSec; + M->maxArray[0]=diff; + M->sum+=diff; + M->iterations++; + + if ( MaxMin) + qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); + else + qsort(M->maxArray, 11, sizeof(uint64_t), cmpintRev); + + printMeas2(txt,M,period, MaxMin); + + if (M->iterations%period == 0 ) { + bzero(M,sizeof(*M)); + + if (!MaxMin) + for (int i=0; i<11; i++) + M->maxArray[i]=INT_MAX; + } + } +} + +#define ceil16_bytes(a) ((((a+15)/16)*16)/8) + +static void fs6Dlunpack(void *out, void *in, int szUnpacked) { + static uint64_t *lut=NULL; + + if (!lut) { + lut=(uint64_t *) malloc(sizeof(*lut)*256); + + for (int i=0; i <256; i++) + for (int j=0; j<8; j++) + ((uint8_t *)(lut+i))[7-j]=(i>>j)&1; + } + + int64_t *out_64 = (int64_t *)out; + int sz=ceil16_bytes(szUnpacked); + + for (int i=0; iframe_parms, proc->frame_prach,proc->subframe_prach)<=0) + return; + + RU_t *ru; + int aa=0; + int ru_aa; + + for (int i=0; inum_RU; i++) { + ru=eNB->RU_list[i]; + + for (ru_aa=0,aa=0; ru_aanb_rx; ru_aa++,aa++) { + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + int ce_level; + + for (ce_level=0; ce_level<4; ce_level++) + eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[i]->prach_rxsigF_br[ce_level][ru_aa]; + } + } + + ocp_rx_prach(eNB, + proc, + eNB->RU_list[0], + header->max_preamble, + header->max_preamble_energy, + header->max_preamble_delay, + header->avg_preamble_energy, + proc->frame_prach, + 0, + false + ); + // run PRACH detection for CE-level 0 only for now when br_flag is set + /* fixme: seems not operational and may overwrite regular LTE prach detection + * OAI code can call is sequence + rx_prach(eNB, + eNB->RU_list[0], + header->max_preamble, + header->max_preamble_energy, + header->max_preamble_delay, + header->avg_preamble_energy, + frame, + 0, + true + ); + */ + LOG_D(PHY,"RACH detection index 0: max preamble: %u, energy: %u, delay: %u, avg energy: %u\n", + header->max_preamble[0], + header->max_preamble_energy[0], + header->max_preamble_delay[0], + header->avg_preamble_energy[0] + ); + return; +} + +void prach_eNB_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc) { + fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); + uint16_t *max_preamble=header->max_preamble; + uint16_t *max_preamble_energy=header->max_preamble_energy; + uint16_t *max_preamble_delay=header->max_preamble_delay; + uint16_t *avg_preamble_energy=header->avg_preamble_energy; + int subframe=proc->subframe_prach; + int frame=proc->frame_prach; + // Fixme: not clear why we call twice with "br" and without + int br_flag=0; + + if (br_flag==1) { + int prach_mask; + prach_mask = is_prach_subframe (&eNB->frame_parms, proc->frame_prach_br, proc->subframe_prach_br); + eNB->UL_INFO.rach_ind_br.rach_indication_body.preamble_list = eNB->preamble_list_br; + int ind = 0; + int ce_level = 0; + /* Save for later, it doesn't work + for (int ind=0,ce_level=0;ce_level<4;ce_level++) { + + if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[ce_level]==1)&& + (prach_mask&(1<<(1+ce_level)) > 0) && // prach is active and CE level has finished its repetitions + (eNB->prach_vars_br.repetition_number[ce_level]== + eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level])) { + + */ + + if (eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[0] == 1) { + if ((eNB->prach_energy_counter == 100) && (max_preamble_energy[0] > eNB->measurements.prach_I0 + eNB->prach_DTX_threshold_emtc[0])) { + eNB->UL_INFO.rach_ind_br.rach_indication_body.number_of_preambles++; + eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind]; // + eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind]; + // note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4 + eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + subframe + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); + eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is + eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1 + ce_level; // CE Level + LOG_I (PHY, "Filling NFAPI indication for RACH %d CELevel %d (mask %x) : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + ind, + ce_level, + prach_mask, + eNB->preamble_list_br[ind].preamble_rel8.timing_advance, + eNB->preamble_list_br[ind].preamble_rel8.preamble, eNB->preamble_list_br[ind].preamble_rel8.rnti, eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type); + } + } + + /* + ind++; + } + } */// ce_level + } else if ((eNB->prach_energy_counter == 100) && + (max_preamble_energy[0] > eNB->measurements.prach_I0+eNB->prach_DTX_threshold)) { + LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", + eNB->Mod_id, + eNB->CC_id, + frame, + subframe, + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_energy[0]%10, + max_preamble_delay[0]); + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 1; + eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = &eNB->preamble_list[0]; + eNB->UL_INFO.rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG; + eNB->UL_INFO.rach_ind.header.message_id = NFAPI_RACH_INDICATION; + eNB->UL_INFO.rach_ind.sfn_sf = frame<<4 | subframe; + eNB->preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG; + eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0]; + eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0]; + eNB->preamble_list[0].preamble_rel8.rnti = 1+subframe; // note: fid is implicitly 0 here + eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0; + eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is + + if (NFAPI_MODE==NFAPI_MODE_PNF) { // If NFAPI PNF then we need to send the message to the VNF + LOG_D(PHY,"Filling NFAPI indication for RACH : SFN_SF:%d TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + NFAPI_SFNSF2DEC(eNB->UL_INFO.rach_ind.sfn_sf), + eNB->preamble_list[0].preamble_rel8.timing_advance, + eNB->preamble_list[0].preamble_rel8.preamble, + eNB->preamble_list[0].preamble_rel8.rnti, + eNB->preamble_list[0].preamble_rel13.rach_resource_type); + oai_nfapi_rach_ind(&eNB->UL_INFO.rach_ind); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 0; + } + + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + } // max_preamble_energy > prach_I0 + 100 + else { + eNB->measurements.prach_I0 = ((eNB->measurements.prach_I0*900)>>10) + ((avg_preamble_energy[0]*124)>>10); + + if (eNB->prach_energy_counter < 100) + eNB->prach_energy_counter++; + } +} + +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, + uint16_t rnti, + int32_t stat) { + static int current_fsf=-1; + int fsf=frame*16+subframe; + uint8_t *bufferZone=eNB->FS6bufferZone; + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + if ( current_fsf != fsf ) { + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_ul_t)+sizeof(fs6_ul_uespec_uci_t); + hULUEuci(newUDPheader)->type=fs6ULcch; + hULUEuci(newUDPheader)->nb_active_ue=0; + } else + for (int i=0; i < FirstUDPheader->nbBlocks-1; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + LOG_D(PHY,"FS6 du, block: %d: adding ul harq/sr: %d, rnti: %d, ueid: %d\n", + curBlock, type, rnti, UEid); + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(newUDPheader)+1); + tmp+=hULUEuci(newUDPheader)->nb_active_ue; + tmp->type=type; + tmp->UEid=UEid; + tmp->frame=frame; + tmp->subframe=subframe; + + if (uci != NULL) + memcpy(&tmp->uci, uci, sizeof(*uci)); + else + tmp->uci.ue_id=0xFFFF; + + if (harq_ack != NULL) + memcpy(tmp->harq_ack, harq_ack, 4); + + tmp->tdd_mapping_mode=tdd_mapping_mode; + tmp->tdd_multiplexing_mask=tdd_multiplexing_mask; + tmp->n0_subband_power_dB=eNB->measurements.n0_subband_power_dB[0][0]; + tmp->rnti=rnti; + tmp->stat=stat; + hULUEuci(newUDPheader)->nb_active_ue++; + newUDPheader->contentBytes+=sizeof(fs6_ul_uespec_uci_element_t); +} + + +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + uint8_t *bufferZone=eNB->FS6bufferZone; + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_ul_t)+sizeof(fs6_ul_uespec_t) + dataLen; + hULUE(newUDPheader)->type=fs6ULsch; + hULUE(newUDPheader)->UE_id=UE_id; + hULUE(newUDPheader)->harq_id=harq_pid; + memcpy(hULUE(newUDPheader)->ulsch_power, + eNB->pusch_vars[UE_id]->ulsch_power, + sizeof(int)*2); + hULUE(newUDPheader)->cqi_crc_status=eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status; + hULUE(newUDPheader)->O_ACK=eNB->ulsch[UE_id]->harq_processes[harq_pid]->O_ACK; + memcpy(hULUE(newUDPheader)->o_ACK, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK, + sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK)); + hULUE(newUDPheader)->ta=lte_est_timing_advance_pusch(eNB, UE_id); + hULUE(newUDPheader)->segment=segmentID; + memcpy(hULUE(newUDPheader)->o, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o, + sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o)); + memcpy(hULUE(newUDPheader)+1, data, dataLen); + hULUE(newUDPheader)->segLen=dataLen; + hULUE(newUDPheader)->r_offset=r_offset; + hULUE(newUDPheader)->G=eNB->ulsch[UE_id]->harq_processes[harq_pid]->G; +} + +void pusch_procedures_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { + uint32_t harq_pid; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; + + if (ulsch->ue_type > NOCE) + harq_pid = 0; + else + harq_pid= subframe2harq_pid(&eNB->frame_parms,frame,subframe); + + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + + if (ulsch->rnti>0) + LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d active: %d handled:%d]\n", + i, harq_pid, frame,subframe,i,ulsch->rnti, + ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->status, ulsch_harq->handled); + + if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + ((ulsch_harq->frame == frame) || (ulsch_harq->repetition_number >1) ) && + ((ulsch_harq->subframe == subframe) || (ulsch_harq->repetition_number >1) ) && + (ulsch_harq->handled == 0)) { + // UE has ULSCH scheduling + for (int rb=0; + rb<=ulsch_harq->nb_rb; + rb++) { + int rb2 = rb+ulsch_harq->first_rb; + eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } + + LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d \n", + eNB->Mod_id, frame, subframe, i); + uint8_t nPRS= fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]; + ulsch->cyclicShift = (ulsch_harq->n_DMRS2 + + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + + nPRS)%12; + AssertFatal(ulsch_harq->TBS>0,"illegal TBS %d\n",ulsch_harq->TBS); + LOG_D(PHY, + "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, Qm %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, ), O_ACK %d, beta_cqi %d \n", + eNB->Mod_id,harq_pid,frame,subframe, + ulsch_harq->dci_alloc, + ulsch_harq->rar_alloc, + ulsch_harq->round, + ulsch_harq->first_rb, + ulsch_harq->nb_rb, + ulsch_harq->Qm, + ulsch_harq->TBS, + ulsch_harq->rvidx, + ulsch->cyclicShift, + ulsch_harq->n_DMRS2, + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, + ulsch_harq->O_ACK, + ulsch->beta_offset_cqi_times8); + start_meas(&eNB->ulsch_demodulation_stats); + eNB->FS6bufferZone=bufferZone; + rx_ulsch(eNB, proc, i); + stop_meas(&eNB->ulsch_demodulation_stats); + // TBD: add datablock for transmission + start_meas(&eNB->ulsch_decoding_stats); + ulsch_decoding(eNB,proc, + i, + 0, // control_only_flag + ulsch_harq->V_UL_DAI, + ulsch_harq->nb_rb>20 ? 1 : 0); + stop_meas(&eNB->ulsch_decoding_stats); + } + } +} + +void phy_procedures_eNB_uespec_RX_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { + //RX processing for ue-specific resources + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + /* TODO: use correct rxdata */ + + if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; + + LOG_D (PHY, "[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n", eNB->Mod_id, frame, subframe); + eNB->rb_mask_ul[0] = 0; + eNB->rb_mask_ul[1] = 0; + eNB->rb_mask_ul[2] = 0; + eNB->rb_mask_ul[3] = 0; + // Fix me here, these should be locked + eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus = 0; + eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs = 0; + // Call SRS first since all others depend on presence of SRS or lack thereof + srs_procedures (eNB, proc); + eNB->first_run_I0_measurements = 0; + uci_procedures (eNB, proc); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // If PNF or monolithic + pusch_procedures_tosplit(bufferZone, bufSize, eNB,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)) { + 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]>max_I0) + max_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; + } + + LOG_I (PHY, "max_I0 %d, min_I0 %d\n", max_I0, min_I0); + } + + return; +} + + +void fill_rx_indication_from_split(uint8_t *bufferZone, PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe, ul_propagation_t *ul_propa) { + nfapi_rx_indication_pdu_t *pdu; + int timing_advance_update; + uint32_t harq_pid; + + if (eNB->ulsch[UE_id]->ue_type > 0) + harq_pid = 0; + else + harq_pid = subframe2harq_pid (&eNB->frame_parms, + frame, subframe); + + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.rx_ind.sfn_sf = frame<<4| subframe; + eNB->UL_INFO.rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG; + pdu = &eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list[eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus]; + // pdu->rx_ue_information.handle = eNB->ulsch[UE_id]->handle; + pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; + pdu->rx_ue_information.rnti = eNB->ulsch[UE_id]->rnti; + pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; + pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; + pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation + pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->decodedBytes; + // estimate timing advance for MAC + timing_advance_update = ul_propa[UE_id].ta; + + // if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} + // if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} + switch (eNB->frame_parms.N_RB_DL) { + case 6: /* nothing to do */ + break; + + case 15: + timing_advance_update /= 2; + break; + + case 25: + timing_advance_update /= 4; + break; + + case 50: + timing_advance_update /= 8; + break; + + case 75: + timing_advance_update /= 12; + break; + + case 100: + timing_advance_update /= 16; + break; + + default: + abort (); + } + + // put timing advance command in 0..63 range + timing_advance_update += 31; + + if (timing_advance_update < 0) + timing_advance_update = 0; + + if (timing_advance_update > 63) + 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]; + + if (SNRtimes10 < -640) + pdu->rx_indication_rel8.ul_cqi = 0; + else if (SNRtimes10 > 635) + pdu->rx_indication_rel8.ul_cqi = 255; + 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, + timing_advance_update); + eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++; + eNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | subframe; + pthread_mutex_unlock(&eNB->UL_INFO_mutex); +} + +void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, ul_propagation_t *ul_propa) { + //LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + uint32_t harq_pid; + uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); + + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; + + if (ulsch->ue_type > NOCE) harq_pid = 0; + else harq_pid=harq_pid0; + + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + + if (ulsch->rnti>0) + LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n", + i, harq_pid, frame,subframe,i,ulsch->rnti, + ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + + if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 0)) { + // UE has ULSCH scheduling + for (int rb=0; + rb<=ulsch_harq->nb_rb; + rb++) { + int rb2 = rb+ulsch_harq->first_rb; + eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } + + start_meas(&eNB->ulsch_decoding_stats); + // This is a new packet, so compute quantities regarding segmentation + ulsch_harq->B = ulsch_harq->TBS+24; + lte_segmentation(NULL, + NULL, + ulsch_harq->B, + &ulsch_harq->C, + &ulsch_harq->Cplus, + &ulsch_harq->Cminus, + &ulsch_harq->Kplus, + &ulsch_harq->Kminus, + &ulsch_harq->F); + ulsch_decoding_data(eNB, proc, i, harq_pid, + ulsch_harq->nb_rb>20 ? 1 : 0); + stop_meas(&eNB->ulsch_decoding_stats); + } // if ((ulsch) && + // (ulsch->rnti>0) && + // (ulsch_harq->status == ACTIVE)) + else if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 1)) { + // this harq process is stale, kill it, this 1024 frames later (10s), consider reducing that + ulsch_harq->status = SCH_IDLE; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << harq_pid); + LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); + } + } // for (i=0; inbDecode > 0) { + notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool); + postDecode(proc, req); + delNotifiedFIFO_elt(req); + } +} + +void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, ul_propagation_t *ul_propa) { + void *bufPtr=bufferZone; + + for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks + if ( ((commonUDP_t *)bufPtr)->contentBytes > sizeof(fs6_ul_t) ) { + int type=hULUE(bufPtr)->type; + + if ( type == fs6ULsch) { + LTE_eNB_ULSCH_t *ulsch =eNB->ulsch[hULUE(bufPtr)->UE_id]; + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hULUE(bufPtr)->harq_id]; + memcpy(ulsch_harq->eUL+hULUE(bufPtr)->r_offset, + hULUE(bufPtr)+1, + hULUE(bufPtr)->segLen); + memcpy(eNB->pusch_vars[hULUE(bufPtr)->UE_id]->ulsch_power, + hULUE(bufPtr)->ulsch_power, + sizeof(int)*2); + ulsch_harq->G=hULUE(bufPtr)->G; + ulsch_harq->cqi_crc_status=hULUE(bufPtr)->cqi_crc_status; + //ulsch_harq->O_ACK= hULUE(bufPtr)->O_ACK; + memcpy(ulsch_harq->o_ACK, hULUE(bufPtr)->o_ACK, + sizeof(ulsch_harq->o_ACK)); + memcpy(ulsch_harq->o,hULUE(bufPtr)->o, sizeof(ulsch_harq->o)); + ul_propa[hULUE(bufPtr)->UE_id].ta=hULUE(bufPtr)->ta; + LOG_D(PHY,"Received ulsch data for: rnti:%x, cqi_crc_status %d O_ACK: %d, segment: %d, seglen: %d \n", + ulsch->rnti, ulsch_harq->cqi_crc_status, ulsch_harq->O_ACK,hULUE(bufPtr)->segment, hULUE(bufPtr)->segLen); + } else if ( type == fs6ULcch ) { + int nb_uci=hULUEuci(bufPtr)->nb_active_ue; + fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); + + for (int j=0; j < nb_uci ; j++) { + LOG_D(PHY,"FS6 cu, block: %d/%d: received ul harq/sr: %d, rnti: %d, ueid: %d\n", + i, j, type, tmp->rnti, tmp->UEid); + eNB->measurements.n0_subband_power_dB[0][0]=tmp->n0_subband_power_dB; + + if (tmp->uci.ue_id != 0xFFFF) + memcpy(&eNB->uci_vars[tmp->UEid],&tmp->uci, sizeof(tmp->uci)); + + if ( tmp->type == fs6ULindicationHarq ) + fill_uci_harq_indication (tmp->UEid, eNB, &eNB->uci_vars[tmp->UEid], + tmp->frame, tmp->subframe, tmp->harq_ack, + tmp->tdd_mapping_mode, tmp->tdd_multiplexing_mask); + else if ( tmp->type == fs6ULindicationSr ) + fill_sr_indication(tmp->UEid, eNB,tmp->rnti,tmp->frame,tmp->subframe,tmp->stat); + else + LOG_E(PHY, "Split FS6: impossible UL harq type\n"); + + tmp++; + } + } else + LOG_E(PHY, "FS6 ul packet type impossible\n" ); + } + + bufPtr+=alignedSize(bufPtr); + } +} + +void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc) { + // The configuration arrived in Dl, so we can extract the UL data + ul_propagation_t ul_propa[NUMBER_OF_UE_MAX]; + recvFs6Ul(bufferZone, nbBlocks, eNB, ul_propa); + + // dirty memory allocation in OAI... + for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) + if ( eNB->uci_vars[i].frame == proc->frame_rx && + eNB->uci_vars[i].subframe == proc->subframe_rx ) + eNB->uci_vars[i].active=0; + + pusch_procedures_fromsplit(bufferZone, nbBlocks, eNB, proc, ul_propa); +} + +void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, int subframe) { + void *bufPtr=bufferZone; + + for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks + if ( ((commonUDP_t *)bufPtr)->contentBytes > sizeof(fs6_dl_t) ) { + int type=hDLUE(bufPtr)->type; + + if ( type == fs6DlConfig) { + int curUE=hDLUE(bufPtr)->UE_id; + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[curUE][0]; + LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[hDLUE(bufPtr)->harq_pid]; +#ifdef PHY_TX_THREAD + dlsch0->active[subframe] = 1; +#else + dlsch0->active = 1; +#endif + dlsch0->harq_ids[frame%2][subframe]=hDLUE(bufPtr)->harq_pid; + dlsch0->rnti=hDLUE(bufPtr)->rnti; + dlsch0->sqrt_rho_a=hDLUE(bufPtr)->sqrt_rho_a; + dlsch0->sqrt_rho_b=hDLUE(bufPtr)->sqrt_rho_b; + dlsch_harq->nb_rb=hDLUE(bufPtr)->nb_rb; + memcpy(dlsch_harq->rb_alloc, hDLUE(bufPtr)->rb_alloc, sizeof(hDLUE(bufPtr)->rb_alloc)); + dlsch_harq->Qm=hDLUE(bufPtr)->Qm; + dlsch_harq->Nl=hDLUE(bufPtr)->Nl; + dlsch_harq->pdsch_start=hDLUE(bufPtr)->pdsch_start; +#ifdef PHY_TX_THREAD + dlsch_harq->CEmode = hDLUE(bufPtr)->CEmode; + dlsch_harq->i0=hDLUE(bufPtr)->i0; + dlsch_harq->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; +#else + dlsch0->i0=hDLUE(bufPtr)->i0; + dlsch0->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; +#endif + fs6Dlunpack(dlsch_harq->eDL, + hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); + LOG_D(PHY,"received %d bits, in harq id: %di fsf: %d.%d, sum %d\n", + hDLUE(bufPtr)->dataLen, hDLUE(bufPtr)->harq_pid, frame, subframe, sum(dlsch_harq->eDL, hDLUE(bufPtr)->dataLen)); + } else if (type == fs6UlConfig) { + int nbUE=(((commonUDP_t *)bufPtr)->contentBytes - sizeof(fs6_dl_t)) / sizeof( fs6_dl_ulsched_t ) ; +#define cpyVal(a) memcpy(&ulsch_harq->a,&hTxULUE(bufPtr)->a, sizeof(ulsch_harq->a)) + + for ( int i=0; i < nbUE; i++ ) { + int curUE=hTxULUE(bufPtr)->UE_id; + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[curUE]; + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hTxULUE(bufPtr)->harq_pid]; + ulsch->ue_type=hTxULUE(bufPtr)->ue_type; + ulsch->harq_mask=hTxULUE(bufPtr)->harq_mask; + ulsch->Mlimit=hTxULUE(bufPtr)->Mlimit; + ulsch->max_turbo_iterations=hTxULUE(bufPtr)->max_turbo_iterations; + ulsch->bundling=hTxULUE(bufPtr)->bundling; + ulsch->beta_offset_cqi_times8=hTxULUE(bufPtr)->beta_offset_cqi_times8; + ulsch->beta_offset_ri_times8=hTxULUE(bufPtr)->beta_offset_ri_times8; + ulsch->beta_offset_harqack_times8=hTxULUE(bufPtr)->beta_offset_harqack_times8; + ulsch->Msg3_active=hTxULUE(bufPtr)->Msg3_active; + ulsch->cyclicShift=hTxULUE(bufPtr)->cyclicShift; + ulsch->cooperation_flag=hTxULUE(bufPtr)->cooperation_flag; + ulsch->num_active_cba_groups=hTxULUE(bufPtr)->num_active_cba_groups; + memcpy(ulsch->cba_rnti,hTxULUE(bufPtr)->cba_rnti,sizeof(ulsch->cba_rnti));//NUM_MAX_CBA_GROUP]; + ulsch->rnti=hTxULUE(bufPtr)->rnti; + ulsch_harq->nb_rb=hTxULUE(bufPtr)->nb_rb; + ulsch_harq->handled=0; + ulsch_harq->status = ACTIVE; + ulsch_harq->frame = frame; + ulsch_harq->subframe = subframe; + ulsch_harq->first_rb=hTxULUE(bufPtr)->first_rb; + ulsch_harq->O_RI=hTxULUE(bufPtr)->O_RI; + ulsch_harq->Or1=hTxULUE(bufPtr)->Or1; + ulsch_harq->Msc_initial=hTxULUE(bufPtr)->Msc_initial; + ulsch_harq->Nsymb_initial=hTxULUE(bufPtr)->Nsymb_initial; + ulsch_harq->V_UL_DAI=hTxULUE(bufPtr)->V_UL_DAI; + ulsch_harq->Qm=hTxULUE(bufPtr)->Qm; + ulsch_harq->srs_active=hTxULUE(bufPtr)->srs_active; + ulsch_harq->TBS=hTxULUE(bufPtr)->TBS; + ulsch_harq->Nsymb_pusch=hTxULUE(bufPtr)->Nsymb_pusch; + cpyVal(dci_alloc); + cpyVal(rar_alloc); + cpyVal(status); + cpyVal(Msg3_flag); + cpyVal(phich_active); + cpyVal(phich_ACK); + cpyVal(previous_first_rb); + cpyVal(B); + cpyVal(G); + //cpyVal(o); + cpyVal(uci_format); + cpyVal(Or2); + cpyVal(o_RI); + cpyVal(o_ACK); + cpyVal(O_ACK); + //cpyVal(q); + cpyVal(o_RCC); + cpyVal(q_ACK); + cpyVal(q_RI); + cpyVal(RTC); + cpyVal(ndi); + cpyVal(round); + cpyVal(rvidx); + cpyVal(Nl); + cpyVal(n_DMRS); + cpyVal(previous_n_DMRS); + cpyVal(n_DMRS2); + cpyVal(delta_TF); + cpyVal(repetition_number ); + cpyVal(total_number_of_repetitions); + LOG_D(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d, O_ACK: %d\n", + ulsch->rnti, frame, subframe, ulsch_harq->O_ACK); + } + } else if ( type == fs6ULConfigCCH ) { + fs6_dl_uespec_ulcch_element_t *tmp=(fs6_dl_uespec_ulcch_element_t *)(hTxULcch(bufPtr)+1); + + for (int i=0; i< hTxULcch(bufPtr)->nb_active_ue; i++ ) + memcpy(&eNB->uci_vars[tmp->UE_id], &tmp->cch_vars, sizeof(tmp->cch_vars)); + } else + LOG_E(PHY, "Impossible block in fs6 DL\n"); + } + + bufPtr+=alignedSize(bufPtr); + } +} + +void phy_procedures_eNB_TX_fromsplit(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int subframe=proc->subframe_tx; + int frame=proc->frame_tx; + //LTE_UL_eNB_HARQ_t *ulsch_harq; + eNB->pdcch_vars[subframe&1].num_pdcch_symbols=hDL(bufferZone)->num_pdcch_symbols; + eNB->pdcch_vars[subframe&1].num_dci=hDL(bufferZone)->num_dci; + uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = hDL(bufferZone)->num_mdci; + eNB->pbch_configured=true; + memcpy(eNB->pbch_pdu,hDL(bufferZone)->pbch_pdu, 4); + + // Remove all scheduled DL, we will populate from the CU sending + for (int UE_id=0; UE_iddlsch[UE_id][0]; + + if ( dlsch0 && dlsch0->rnti>0 ) { +#ifdef PHY_TX_THREAD + dlsch0->active[subframe] = 0; +#else + dlsch0->active = 0; +#endif + } + } + + rcvFs6DL(bufferZone, nbBlocks, eNB, frame, subframe); + + if (do_meas==1) { + start_meas(&eNB->phy_proc_tx); + start_meas(&eNB->dlsch_common_and_dci); + } + + // clear the transmit data array for the current subframe + for (int aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { + memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti)], + 0, fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); + } + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + if (is_pmch_subframe(frame,subframe,fp)) { + pmch_procedures(eNB,proc); + } else { + // this is not a pmch subframe, so generate PSS/SSS/PBCH + common_signal_procedures(eNB,frame, subframe); + } + } + + // clear previous allocation information for all UEs + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + //if (eNB->dlsch[i][0]) + //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + } + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + for (int i=0; i< hDL(bufferZone)->num_dci; i++) + eNB->pdcch_vars[subframe&1].dci_alloc[i]=hDL(bufferZone)->dci_alloc[i]; + + LOG_D (PHY, "Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %" PRIu8 ")\n", frame, subframe, hDL(bufferZone)->num_dci); + generate_dci_top(hDL(bufferZone)->num_pdcch_symbols, + hDL(bufferZone)->num_dci, + &eNB->pdcch_vars[subframe&1].dci_alloc[0], + 0, + hDL(bufferZone)->amp, + fp, + eNB->common_vars.txdataF, + subframe); + + if (num_mdci > 0) { + LOG_D (PHY, "[eNB %" PRIu8 "] Frame %d, subframe %d: Calling generate_mdci_top (mpdcch) (num_dci %" PRIu8 ")\n", eNB->Mod_id, frame, subframe, num_mdci); + generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF); + } + } + + for (int UE_id=0; UE_iddlsch[UE_id][0]; + LTE_eNB_DLSCH_t *dlsch1 = eNB->dlsch[UE_id][1]; + + if ((dlsch0)&&(dlsch0->rnti>0)&& +#ifdef PHY_TX_THREAD + (dlsch0->active[subframe] == 1) +#else + (dlsch0->active == 1) +#endif + ) { + uint64_t sum=0; + + for ( int i= subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti); + i< (subframe+1) * fp->ofdm_symbol_size * (fp->symbols_per_tti); + i++) + sum+=((int32_t *)(eNB->common_vars.txdataF[0]))[i]; + + LOG_D(PHY,"frame: %d, subframe: %d, sum of dlsch mod v1: %lx\n", frame, subframe, sum); + int harq_pid=dlsch0->harq_ids[frame%2][subframe]; + pdsch_procedures(eNB, + proc, + harq_pid, + dlsch0, + dlsch1); + } + } + + eNB->phich_vars[subframe&1]=hDL(bufferZone)->phich_vars; + generate_phich_top(eNB, + proc, + AMP); +} + +#define cpyToDu(a) hTxULUE(newUDPheader)->a=ulsch->a +#define cpyToDuHarq(a) hTxULUE(newUDPheader)->a=ulsch_harq->a +#define memcpyToDuHarq(a) memcpy(&hTxULUE(newUDPheader)->a,&ulsch_harq->a, sizeof(ulsch_harq->a)); + +void appendFs6TxULUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int curUE, LTE_eNB_ULSCH_t *ulsch, int frame, int subframe) { + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_ulsched_t); + // We skip the fs6 DL header, that is populated by caller + // This header will be duplicated during sending + hTxULUE(newUDPheader)->type=fs6UlConfig; + hTxULUE(newUDPheader)->UE_id=curUE; + int harq_pid; + + if (ulsch->ue_type > NOCE) + // LTE-M case + harq_pid = 0; + else + harq_pid = subframe2harq_pid(fp, frame, subframe); + + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[harq_pid]; + hTxULUE(newUDPheader)->harq_pid=harq_pid; + cpyToDu(ue_type); + cpyToDu(harq_mask); + cpyToDu(Mlimit); + cpyToDu(max_turbo_iterations); + cpyToDu(bundling); + cpyToDu(beta_offset_cqi_times8); + cpyToDu(beta_offset_ri_times8); + cpyToDu(beta_offset_harqack_times8); + cpyToDu(Msg3_active); + cpyToDu(cyclicShift); + cpyToDu(cooperation_flag); + cpyToDu(num_active_cba_groups); + memcpy(hTxULUE(newUDPheader)->cba_rnti,ulsch->cba_rnti,sizeof(ulsch->cba_rnti));//NUM_MAX_CBA_GROUP]; + cpyToDu(rnti); + cpyToDuHarq(nb_rb); + cpyToDuHarq(Msc_initial); + cpyToDuHarq(Nsymb_initial); + cpyToDuHarq(O_RI); + cpyToDuHarq(Or1); + cpyToDuHarq(first_rb); + cpyToDuHarq(V_UL_DAI); + cpyToDuHarq(Qm); + cpyToDuHarq(srs_active); + cpyToDuHarq(TBS); + cpyToDuHarq(Nsymb_pusch); + memcpyToDuHarq(dci_alloc); + memcpyToDuHarq(rar_alloc); + memcpyToDuHarq(status); + memcpyToDuHarq(Msg3_flag); + memcpyToDuHarq(phich_active); + memcpyToDuHarq(phich_ACK); + memcpyToDuHarq(previous_first_rb); + memcpyToDuHarq(B); + memcpyToDuHarq(G); + //memcpyToDuHarq(o); + memcpyToDuHarq(uci_format); + memcpyToDuHarq(Or2); + memcpyToDuHarq(o_RI); + memcpyToDuHarq(o_ACK); + memcpyToDuHarq(O_ACK); + //memcpyToDuHarq(q); + memcpyToDuHarq(o_RCC); + memcpyToDuHarq(q_ACK); + memcpyToDuHarq(q_RI); + memcpyToDuHarq(RTC); + memcpyToDuHarq(ndi); + memcpyToDuHarq(round); + memcpyToDuHarq(rvidx); + memcpyToDuHarq(Nl); + memcpyToDuHarq(n_DMRS); + memcpyToDuHarq(previous_n_DMRS); + memcpyToDuHarq(n_DMRS2); + memcpyToDuHarq(delta_TF); + memcpyToDuHarq(repetition_number ); + memcpyToDuHarq(total_number_of_repetitions); + LOG_D(PHY,"Added request to perform ulsch for: rnti:%x, fsf: %d/%d\n", ulsch->rnti, frame, subframe); +} + +void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_t harq_pid, LTE_eNB_DLSCH_t *dlsch0, LTE_DL_eNB_HARQ_t *harqData, int frame, int subframe) { + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + int UEdataLen= get_G(fp, + harqData->nb_rb, + harqData->rb_alloc, + harqData->Qm, + harqData->Nl, + harqData->pdsch_start, + frame,subframe, + 0); + AssertFatal(firstFreeByte+ceil16_bytes(UEdataLen)+sizeof(fs6_dl_t) <= bufferZone+FS6_BUF_SIZE, ""); + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) + ceil16_bytes(UEdataLen); + // We skip the fs6 DL header, that is populated by caller + // This header will be duplicated during sending + hDLUE(newUDPheader)->type=fs6DlConfig; + hDLUE(newUDPheader)->UE_id=UE_id; + hDLUE(newUDPheader)->harq_pid=harq_pid; + hDLUE(newUDPheader)->rnti=dlsch0->rnti; + hDLUE(newUDPheader)->sqrt_rho_a=dlsch0->sqrt_rho_a; + hDLUE(newUDPheader)->sqrt_rho_b=dlsch0->sqrt_rho_b; + hDLUE(newUDPheader)->nb_rb=harqData->nb_rb; + memcpy(hDLUE(newUDPheader)->rb_alloc, harqData->rb_alloc, sizeof(harqData->rb_alloc)); + hDLUE(newUDPheader)->Qm=harqData->Qm; + hDLUE(newUDPheader)->Nl=harqData->Nl; + hDLUE(newUDPheader)->pdsch_start=harqData->pdsch_start; +#ifdef PHY_TX_THREAD + hDLUE(newUDPheader)->CEmode=harqData->CEmode; + hDLUE(newUDPheader)->i0=harqData->i0; + hDLUE(newUDPheader)->sib1_br_flag=harqData->sib1_br_flag; +#else + hDLUE(newUDPheader)->i0=dlsch0->i0; + hDLUE(newUDPheader)->sib1_br_flag=dlsch0->sib1_br_flag; +#endif + hDLUE(newUDPheader)->dataLen=UEdataLen; + fs6Dlpack(hDLUE(newUDPheader)+1, harqData->eDL, UEdataLen); + LOG_D(PHY,"sending %d bits, in harq id: %di fsf: %d.%d, sum %d\n", + UEdataLen, harq_pid, frame, subframe, sum(harqData->eDL, UEdataLen)); + //for (int i=0; i < UEdataLen; i++) + //LOG_D(PHY,"buffer ei[%d]:%hhx\n", i, ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); +} + +void appendFs6DLUEcch(uint8_t *bufferZone, PHY_VARS_eNB *eNB, int frame, int subframe) { + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + bool first_UE=true; + + for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) { + LTE_eNB_UCI *uci = &(eNB->uci_vars[i]); + + if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) { + LOG_D(PHY,"Frame %d, subframe %d: adding uci procedures (type %d) for %d \n", + frame, + subframe, + uci->type, + i); + + if ( first_UE ) { + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_ulcch_t); + hTxULcch(newUDPheader)->type=fs6ULConfigCCH; + hTxULcch(newUDPheader)->nb_active_ue=0; + first_UE=false; + } + + fs6_dl_uespec_ulcch_element_t *tmp=(fs6_dl_uespec_ulcch_element_t *)(hTxULcch(newUDPheader)+1); + tmp+=hTxULcch(newUDPheader)->nb_active_ue; + tmp->UE_id=i; + memcpy(&tmp->cch_vars,uci, sizeof(tmp->cch_vars)); + hTxULcch(newUDPheader)->nb_active_ue++; + newUDPheader->contentBytes+=sizeof(fs6_dl_uespec_ulcch_element_t); + } + } +} + +void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { + int frame=proc->frame_tx; + int subframe=proc->subframe_tx; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + + if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL)) { + LOG_W(HW,"no sending in eNB_TX\n"); + return; + } + + // clear previous allocation information for all UEs + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + //if (eNB->dlsch[i][0]) + //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + } + + // Send to DU the UL scheduled for future UL subframe + for (int i=0; iulsch[i]; + + if (ulsch->ue_type > NOCE) + harq_pid = 0; + else + harq_pid= subframe2harq_pid(&eNB->frame_parms,frame,subframe); + + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + + if (ulsch->rnti>0) { + LOG_D(PHY,"check in UL scheduled harq %d: rnti %d, tx frame %d/%d, ulsch: %d, %d/%d (handled: %d)\n", + harq_pid, ulsch->rnti, frame, subframe, ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + } + + for (int k=0; k<8; k++) { + ulsch_harq = ulsch->harq_processes[k]; + + if (ulsch && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 0) + ) + appendFs6TxULUE(bufferZone, + fp, + i, + ulsch, + frame, + subframe + ); + } + } + + appendFs6DLUEcch(bufferZone, + eNB, + frame, + subframe + ); + uint8_t num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; + uint8_t num_dci = eNB->pdcch_vars[subframe&1].num_dci; + uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci; + memcpy(hDL(bufferZone)->pbch_pdu,eNB->pbch_pdu,4); + + if ( num_dci <= 8 ) + LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); + else { + LOG_E(PHY, "Num dci too large for current FS6 implementation, reducing to 8 dci (was %d)\n", num_dci); + num_dci=8; + } + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + hDL(bufferZone)->num_pdcch_symbols=num_pdcch_symbols; + hDL(bufferZone)->num_dci=num_dci; + hDL(bufferZone)->num_mdci=num_mdci; + hDL(bufferZone)->amp=AMP; + + for (int i=0; i< hDL(bufferZone)->num_dci; i++) + hDL(bufferZone)->dci_alloc[i]=eNB->pdcch_vars[subframe&1].dci_alloc[i]; + + LOG_D(PHY, "pbch configured: %d\n", eNB->pbch_configured); + } + + if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci); + + if (do_meas==1) start_meas(&eNB->dlsch_ue_specific); + + for (int UE_id=0; UE_iddlsch[UE_id][0]; + + if ((dlsch0)&&(dlsch0->rnti>0)&& +#ifdef PHY_TX_THREAD + (dlsch0->active[subframe] == 1) +#else + (dlsch0->active == 1) +#endif + ) { + // get harq_pid + int harq_pid = dlsch0->harq_ids[frame%2][subframe]; + AssertFatal(harq_pid>=0,"harq_pid is negative\n"); + + if (harq_pid>=8) { + if (dlsch0->ue_type == NOCE) + LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x [ %1d.%1d.%1d.%1d.%1d.%1d.%1d.%1d\n", harq_pid,UE_id,frame,subframe,dlsch0->rnti, + dlsch0->harq_ids[frame%2][0], + dlsch0->harq_ids[frame%2][1], + dlsch0->harq_ids[frame%2][2], + dlsch0->harq_ids[frame%2][3], + dlsch0->harq_ids[frame%2][4], + dlsch0->harq_ids[frame%2][5], + dlsch0->harq_ids[frame%2][6], + dlsch0->harq_ids[frame%2][7]); + } else { + if (dlsch_procedures(eNB, + proc, + harq_pid, + dlsch0, + &eNB->UE_stats[(uint32_t)UE_id])) { + // data in: dlsch0 harq_processes[harq_pid]->e + /* length + get_G(fp, + dlsch_harq->nb_rb, + dlsch_harq->rb_alloc, + dlsch_harq->Qm, + dlsch_harq->Nl, + dlsch_harq->pdsch_start, + frame,subframe, + 0) + need harq_pid + */ + LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[harq_pid]; + appendFs6DLUE(bufferZone, + fp, + UE_id, + harq_pid, + dlsch0, + dlsch_harq, + frame, + subframe + ); + } + } + } else if ((dlsch0)&&(dlsch0->rnti>0)&& +#ifdef PHY_TX_THREAD + (dlsch0->active[subframe] == 0) +#else + (dlsch0->active == 0) +#endif + ) { + // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) + //dlsch0->subframe_tx[subframe]=0; + } + } + + hDL(bufferZone)->phich_vars=eNB->phich_vars[subframe&1]; + + if (do_meas==1) stop_meas(&eNB->dlsch_ue_specific); + + if (do_meas==1) stop_meas(&eNB->phy_proc_tx); + + // MBMS is not working in OAI + if (hDL(bufferZone)->num_mdci) abort(); + + return; +} + +void *DL_du_fs6(void *arg) { + RU_t *ru=(RU_t *)arg; + static uint64_t lastTS; + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + initStaticTime(begingWait); + initStaticTime(begingProcessing); + initRefTimes(fullLoop); + initRefTimes(DuHigh); + initRefTimes(DuLow); + initRefTimes(transportTime); + + while (1) { + for (int i=0; inum_eNB; i++) { + initBufferZone(bufferZone); + pickStaticTime(begingWait); + int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentCUv0 ); + updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait CU"); + + if (nb_blocks > 0) { + if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti < hUDP(bufferZone)->timestamp) { + LOG_E(HW,"Missed a subframe: expecting: %lu, received %lu\n", + lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, + hUDP(bufferZone)->timestamp); + } else if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti > hUDP(bufferZone)->timestamp) { + LOG_E(HW,"Received a subframe in past time from CU (dropping it): expecting: %lu, received %lu\n", + lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, + hUDP(bufferZone)->timestamp); + } + + pickStaticTime(begingProcessing); + lastTS=hUDP(bufferZone)->timestamp; + setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti, &L1proc); + measTransportTime(hDL(bufferZone)->DuClock, hDL(bufferZone)->CuSpentMicroSec, + &transportTime, 1000, false, "Transport time, to CU + from CU for one subframe"); + phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &L1proc, 1); + updateTimesReset(begingProcessing, &DuHigh, 1000, false, "DU high layer1 processing for DL"); + } else + LOG_E(PHY,"DL not received for subframe\n"); + } + + pickStaticTime(begingProcessing); + feptx_prec(ru, L1proc.frame_tx,L1proc.subframe_tx ); + feptx_ofdm(ru, L1proc.frame_tx,L1proc.subframe_tx ); + ocp_tx_rf(ru, &L1proc); + updateTimesReset(begingProcessing, &DuLow, 1000, false, "DU low layer1 processing for DL"); + + if ( IS_SOFTMODEM_RFSIM ) + return NULL; + } + + return NULL; +} + +void UL_du_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { + initStaticTime(begingWait); + initRefTimes(fullLoop); + pickStaticTime(begingWait); + rx_rf(ru, proc); + updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait USRP"); + // front end processing: convert from time domain to frequency domain + // fills rxdataF buffer + fep_full(ru, proc->subframe_rx); + // Fixme: datamodel issue + PHY_VARS_eNB *eNB = RC.eNB[0][0]; + + if (NFAPI_MODE==NFAPI_MODE_PNF) { + // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick + //add_subframe(&frame, &subframe, 4); + //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); + oai_subframe_ind(proc->frame_rx, proc->subframe_rx); + } + + initBufferZone(bufferZone); + hUDP(bufferZone)->timestamp=proc->timestamp_rx; + prach_eNB_tosplit(bufferZone, FS6_BUF_SIZE, eNB, proc ); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX_tosplit(bufferZone, FS6_BUF_SIZE, eNB, proc ); + } + + if (hUDP(bufferZone)->nbBlocks==0) { + hUDP(bufferZone)->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) + hUDP(bufferZone)->blockID=0; + hUDP(bufferZone)->contentBytes=sizeof(fs6_ul_t); + } + + for (int i=0; inum_eNB; i++) { + sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_ul_t), CTsentDUv0); + } +} + +void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t DuClock, uint64_t startCycle) { + initRefTimes(CUprocessing); + // Fixme: datamodel issue + PHY_VARS_eNB *eNB = RC.eNB[0][0]; + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.frame = proc->frame_rx; + eNB->UL_INFO.subframe = proc->subframe_rx; + eNB->UL_INFO.module_id = eNB->Mod_id; + eNB->UL_INFO.CC_id = eNB->CC_id; + eNB->if_inst->UL_indication(&eNB->UL_INFO, proc); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + initBufferZone(bufferZone); + phy_procedures_eNB_TX_tosplit(bufferZone, eNB, proc, 1, bufferZone, FS6_BUF_SIZE); + hUDP(bufferZone)->timestamp=proc->timestamp_tx; + + if (hUDP(bufferZone)->nbBlocks==0) { + hUDP(bufferZone)->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) + hUDP(bufferZone)->blockID=0; + hUDP(bufferZone)->contentBytes=sizeof(fs6_dl_t); + } + + hDL(bufferZone)->DuClock=DuClock; + hDL(bufferZone)->CuSpentMicroSec=(rdtsc()-startCycle)/(cpuf*1000); + updateTimesReset(startCycle, &CUprocessing, 1000, true,"CU entire processing from recv to send"); + sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t), CTsentCUv0 ); + return; +} + +void UL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t *TS, uint64_t *DuClock, uint64_t *startProcessing) { + initBufferZone(bufferZone); + initStaticTime(begingWait); + initRefTimes(fullLoop); + pickStaticTime(begingWait); + int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentDUv0 ); + * DuClock=hUDP(bufferZone)->senderClock; + * startProcessing=rdtsc(); + updateTimesReset(begingWait, &fullLoop, 1000, false, "CU wait DU"); + + if (nb_blocks ==0) { + LOG_W(PHY, "CU lost a subframe\n"); + return; + } + + if (nb_blocks != hUDP(bufferZone)->nbBlocks ) + LOG_W(PHY, "received %d blocks for %d expected\n", nb_blocks, hUDP(bufferZone)->nbBlocks); + + if ( *TS != hUDP(bufferZone)->timestamp ) { + LOG_W(HW, "CU received time: %lu instead of %lu expected\n", hUDP(bufferZone)->timestamp, *TS); + *TS=hUDP(bufferZone)->timestamp; + } + + setAllfromTS(hUDP(bufferZone)->timestamp, proc); + PHY_VARS_eNB *eNB = RC.eNB[0][0]; + + if (is_prach_subframe(&eNB->frame_parms, proc->frame_prach,proc->subframe_prach)>0) + prach_eNB_fromsplit(bufferZone, sizeof(bufferZone), eNB, proc); + + release_UE_in_freeList(eNB->Mod_id); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX_fromsplit(bufferZone, nb_blocks, eNB, proc); + } +} + +void *cu_fs6(void *arg) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + RU_t *ru = (RU_t *)arg; + //RU_proc_t *proc = &ru->proc; + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + phy_init_RU(ru); + wait_sync("ru_thread"); + char remoteIP[1024]; + strncpy(remoteIP,get_softmodem_params()->split73+3, 1023); //three first char should be cu: or du: + char port_def[256]=DU_PORT; + for (int i=0; i <1000; i++) + if (remoteIP[i]==':') { + strncpy(port_def,remoteIP+i+1,255); + remoteIP[i]=0; + break; + } + + AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, port_def, &sockFS6), ""); + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + uint64_t timeStamp=0; + initStaticTime(begingWait); + initStaticTime(begingWait2); + initRefTimes(waitDUAndProcessingUL); + initRefTimes(makeSendDL); + initRefTimes(fullLoop); + uint64_t DuClock=0, startProcessing=0; + + while(1) { + timeStamp+=ru->frame_parms->samples_per_tti; + updateTimesReset(begingWait, &fullLoop, 1000, true, "CU for full SubFrame (must be less 1ms)"); + pickStaticTime(begingWait); + UL_cu_fs6(ru, &L1proc, &timeStamp, &DuClock, &startProcessing); + updateTimesReset(begingWait, &waitDUAndProcessingUL, 1000, true,"CU Time in wait Rx + Ul processing"); + pickStaticTime(begingWait2); + DL_cu_fs6(ru, &L1proc, DuClock, startProcessing); + updateTimesReset(begingWait2, &makeSendDL, 1000, true,"CU Time in DL build+send"); + } + + return NULL; +} + +void *du_fs6(void *arg) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + RU_t *ru = (RU_t *)arg; + //RU_proc_t *proc = &ru->proc; + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + phy_init_RU(ru); + init_rf(ru); + wait_sync("ru_thread"); + char remoteIP[1024]; + strncpy(remoteIP,get_softmodem_params()->split73+3,1023); //three first char should be cu: or du: + char port_def[256]=CU_PORT; + for (int i=0; i <1000; i++) + if (remoteIP[i]==':') { + strncpy(port_def,remoteIP+i+1,255); + remoteIP[i]=0; + break; + } + AssertFatal(createUDPsock(NULL, DU_PORT, remoteIP, port_def, &sockFS6), ""); + + if (ru->rfdevice.trx_start_func(&ru->rfdevice) != 0) + LOG_E(HW,"Could not start the RF device\n"); + else + LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + + initStaticTime(begingWait); + initRefTimes(waitRxAndProcessingUL); + initRefTimes(fullLoop); + pthread_t t; + + if ( !IS_SOFTMODEM_RFSIM ) + threadCreate(&t, DL_du_fs6, (void *)ru, "MainDuTx", -1, OAI_PRIORITY_RT_MAX); + + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + + while(!oai_exit) { + updateTimesReset(begingWait, &fullLoop, 1000, true,"DU for full SubFrame (must be less 1ms)"); + pickStaticTime(begingWait); + UL_du_fs6(ru, &L1proc); + + if ( IS_SOFTMODEM_RFSIM ) + DL_du_fs6((void *)ru); + + updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); + } + + ru->rfdevice.trx_end_func(&ru->rfdevice); + LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); + return NULL; +} diff --git a/executables/main-ocp.c b/executables/main-ocp.c new file mode 100644 index 0000000000..d2ee9418dc --- /dev/null +++ b/executables/main-ocp.c @@ -0,0 +1,1401 @@ +/* +* 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 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* 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 +*/ + + +/* + * This file replaces + * targets/RT/USER/lte-softmodem.c + * targets/RT/USER/rt_wrapper.c + * targets/RT/USER/lte-ru.c + * targets/RT/USER/lte-enb.c + * targets/RT/USER/ru_control.c + * openair1/SCHED/prach_procedures.c + * The merger of OpenAir central code to this branch + * should check if these 3 files are modified and analyze if code code has to be copied in here + */ +#define _GNU_SOURCE +#include + +#include +#include +#include +static int DEFBANDS[] = {7}; +static int DEFENBS[] = {0}; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +pthread_cond_t nfapi_sync_cond; +pthread_mutex_t nfapi_sync_mutex; +int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex +pthread_cond_t sync_cond; +pthread_mutex_t sync_mutex; +int sync_var=-1; //!< protected by mutex \ref sync_mutex. +int config_sync_var=-1; +volatile int oai_exit = 0; +double cpuf; +uint16_t sf_ahead=4; +int otg_enabled; +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int split73; +char * split73_config; +int split73; + +static void *ru_thread( void *param ); +void kill_RU_proc(RU_t *ru) { +} +void kill_eNB_proc(int inst) { +} +void free_transport(PHY_VARS_eNB *eNB) { +} +void reset_opp_meas(void) { +} +extern void phy_free_RU(RU_t *); + +void exit_function(const char *file, const char *function, const int line, const char *s) { + if (s != NULL) { + printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); + } + + close_log_mem(); + oai_exit = 1; + + if (RC.ru == NULL) + exit(-1); // likely init not completed, prevent crash or hang, exit now... + + for (int ru_id=0; ru_idrfdevice.trx_end_func) { + RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_end_func = NULL; + } + + if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) { + RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_end_func = NULL; + } + } + + sleep(1); //allow lte-softmodem threads to exit first + exit(1); +} + +// Fixme: there are many mistakes in the datamodel and in redondant variables +// TDD is also mode complex +void setAllfromTS(uint64_t TS, L1_rxtx_proc_t *proc) { + for (int i=0; i < RC.nb_inst; i++) { + for (int j=0; jframe_parms; + uint64_t TStx=TS+(sf_ahead)*fp->samples_per_tti; + uint64_t TSrach=TS;//-fp->samples_per_tti; + proc->timestamp_rx= TS; + proc->timestamp_tx= TStx; + proc->subframe_rx= (TS / fp->samples_per_tti)%10; + proc->subframe_prach=(TSrach / fp->samples_per_tti)%10; + proc->subframe_prach_br=(TSrach / fp->samples_per_tti)%10; + proc->frame_rx= (TS / (fp->samples_per_tti*10))&1023; + proc->frame_prach= (TSrach / (fp->samples_per_tti*10))&1023; + proc->frame_prach_br=(TSrach / (fp->samples_per_tti*10))&1023; + proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; + proc->subframe_tx= (TStx / fp->samples_per_tti)%10; + } + } + + return; +} + +void init_RU_proc(RU_t *ru) { + pthread_t t; + + switch(split73) { + case SPLIT73_CU: + threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); + break; + case SPLIT73_DU: + threadCreate(&t, du_fs6, (void *)ru, "MainDuRx", -1, OAI_PRIORITY_RT_MAX); + break; + default: + threadCreate(&t, ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX); + } +} + +// Create per UE structures +void init_transport(PHY_VARS_eNB *eNB) { + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + LOG_I(PHY, "Initialise transport\n"); + + for (int i=0; idlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp)) != NULL, + "Can't get eNB dlsch structures for UE %d \n", i); + eNB->dlsch[i][j]->rnti=0; + LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti); + } + + LOG_D(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i); + AssertFatal((eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0)) != NULL, + "Can't get eNB ulsch structures\n"); + // this is the transmission mode for the signalling channels + // this will be overwritten with the real transmission mode by the RRC once the UE is connected + eNB->transmission_mode[i] = fp->nb_antenna_ports_eNB==1 ? 1 : 2; + } + + // ULSCH for RA + AssertFatal( (eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0)) !=NULL, + "Can't get eNB ulsch structures\n"); + eNB->dlsch_SI = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); + LOG_D(PHY,"eNB %d.%d : SI %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_SI); + eNB->dlsch_ra = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); + LOG_D(PHY,"eNB %d.%d : RA %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_ra); + eNB->dlsch_MCH = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); + LOG_D(PHY,"eNB %d.%d : MCH %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_MCH); + eNB->rx_total_gain_dB=130; + + for(int i=0; imu_mimo_mode[i].dl_pow_off = 2; + + eNB->check_for_total_transmissions = 0; + eNB->check_for_MUMIMO_transmissions = 0; + eNB->FULL_MUMIMO_transmissions = 0; + eNB->check_for_SUMIMO_transmissions = 0; + fp->pucch_config_common.deltaPUCCH_Shift = 1; +} + +void init_eNB_afterRU(void) { + for (int inst=0; instframe_parms.nb_antennas_rx = 0; + eNB->frame_parms.nb_antennas_tx = 0; + eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *)); + + for (int ce_level=0; ce_level<4; ce_level++) { + eNB->prach_vars_br.rxsigF[ce_level] = (int16_t **)malloc16(64*sizeof(int16_t *)); + } + + for (int ru_id=0,aa=0; ru_idnum_RU; ru_id++) { + eNB->frame_parms.nb_antennas_rx += eNB->RU_list[ru_id]->nb_rx; + eNB->frame_parms.nb_antennas_tx += eNB->RU_list[ru_id]->nb_tx; + AssertFatal(eNB->RU_list[ru_id]->common.rxdataF!=NULL, + "RU %d : common.rxdataF is NULL\n", + eNB->RU_list[ru_id]->idx); + AssertFatal(eNB->RU_list[ru_id]->prach_rxsigF!=NULL, + "RU %d : prach_rxsigF is NULL\n", + eNB->RU_list[ru_id]->idx); + + for (int i=0; iRU_list[ru_id]->nb_rx; aa++,i++) { + LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa); + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[i]; + + for (int ce_level=0; ce_level<4; ce_level++) + eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i]; + + eNB->common_vars.rxdataF[aa] = eNB->RU_list[ru_id]->common.rxdataF[i]; + } + } + + AssertFatal( eNB->frame_parms.nb_antennas_rx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); + AssertFatal( eNB->frame_parms.nb_antennas_tx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); + LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx); + init_transport(eNB); + //init_precoding_weights(RC.eNB[inst][CC_id]); + } + } +} + +void init_eNB(int single_thread_flag,int wait_for_sync) { + AssertFatal(RC.eNB != NULL,"RC.eNB must have been allocated\n"); + + for (int inst=0; instabstraction_flag = 0; + eNB->single_thread_flag = single_thread_flag; + AssertFatal((eNB->if_inst = IF_Module_init(inst))!=NULL,"Cannot register interface"); + eNB->if_inst->schedule_response = schedule_response; + eNB->if_inst->PHY_config_req = phy_config_request; + memset((void *)&eNB->UL_INFO,0,sizeof(eNB->UL_INFO)); + memset((void *)&eNB->Sched_INFO,0,sizeof(eNB->Sched_INFO)); + pthread_mutex_init( &eNB->UL_INFO_mutex, NULL); + LOG_I(PHY,"Setting indication lists\n"); + eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = eNB->rx_pdu_list; + eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = eNB->crc_pdu_list; + eNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = eNB->sr_pdu_list; + eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list; + eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_pdu_list = eNB->cqi_pdu_list; + eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list; + eNB->prach_energy_counter = 0; + } + } + + SET_LOG_DEBUG(PRACH); +} + +void stop_eNB(int nb_inst) { + for (int inst=0; instframe_parms; + openair0_config_t *cfg = &ru->openair0_cfg; + //printf("////////////////numerology in config = %d\n",numerology); + int numerology = get_softmodem_params()->numerology; + + if(fp->N_RB_DL == 100) { + if(numerology == 0) { + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + } else if(numerology == 1) { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } else if(numerology == 2) { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } else { + LOG_E(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; + cfg->rx_bw = 10e6; + } + } else if(fp->N_RB_DL == 50) { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } else if (fp->N_RB_DL == 25) { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 2.5e6; + cfg->rx_bw = 2.5e6; + } else if (fp->N_RB_DL == 6) { + cfg->sample_rate=1.92e6; + cfg->samples_per_frame = 19200; + cfg->tx_bw = 1.5e6; + cfg->rx_bw = 1.5e6; + } else AssertFatal(1==0,"Unknown N_RB_DL %d\n",fp->N_RB_DL); + + if (fp->frame_type==TDD) + cfg->duplex_mode = duplex_mode_TDD; + else //FDD + cfg->duplex_mode = duplex_mode_FDD; + + cfg->Mod_id = 0; + cfg->num_rb_dl=fp->N_RB_DL; + cfg->tx_num_channels=ru->nb_tx; + cfg->rx_num_channels=ru->nb_rx; + cfg->clock_source=get_softmodem_params()->clock_source; + + for (i=0; inb_tx; i++) { + cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; + cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; + cfg->tx_gain[i] = (double)ru->att_tx; + cfg->rx_gain[i] = ru->max_rxgain-(double)ru->att_rx; + cfg->configFilename = rf_config_file; + 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], + cfg->rx_freq[i]); + } +} + +/* this function maps the RU tx and rx buffers to the available rf chains. + Each rf chain is is addressed by the card number and the chain on the card. The + rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple + antennas are mapped to successive RF chains on the same card. */ +int setup_RU_buffers(RU_t *ru) { + //uint16_t N_TA_offset = 0; + LTE_DL_FRAME_PARMS *frame_parms; + AssertFatal(ru, "ru is NULL"); + frame_parms = ru->frame_parms; + LOG_I(PHY,"setup_RU_buffers: frame_parms = %p\n",frame_parms); + + if (frame_parms->frame_type == TDD) { + if (frame_parms->N_RB_DL == 100) { + ru->N_TA_offset = 624; + } else if (frame_parms->N_RB_DL == 50) { + ru->N_TA_offset = 624/2; + ru->sf_extension /= 2; + ru->end_of_burst_delay /= 2; + } else if (frame_parms->N_RB_DL == 25) { + ru->N_TA_offset = 624/4; + ru->sf_extension /= 4; + ru->end_of_burst_delay /= 4; + } else { + LOG_E(PHY,"not handled, todo\n"); + exit(1); + } + } else { + ru->N_TA_offset = 0; + ru->sf_extension = 0; + ru->end_of_burst_delay = 0; + } + + return(0); +} + +void init_precoding_weights(PHY_VARS_eNB *eNB) { + int layer,ru_id,aa,re,ue,tb; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + RU_t *ru; + LTE_eNB_DLSCH_t *dlsch; + + // init precoding weigths + for (ue=0; uedlsch[ue][tb]; + + for (layer=0; layer<4; layer++) { + int nb_tx=0; + + for (ru_id=0; ru_idnb_tx; + } + + dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(nb_tx*sizeof(int32_t *)); + + for (aa=0; aaue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t)); + + for (re=0; reofdm_symbol_size; re++) { + dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; + } + } + } + } + } +} + +void ocp_rx_prach(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + RU_t *ru, + uint16_t *max_preamble, + uint16_t *max_preamble_energy, + uint16_t *max_preamble_delay, + uint16_t *avg_preamble_energy, + uint16_t Nf, + uint8_t tdd_mapindex, + uint8_t br_flag) { + int i; + int prach_mask=0; + + if (br_flag == 0) { + rx_prach0(eNB,ru,proc->frame_prach, proc->subframe_prach, + max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); + } else { // This is procedure for eMTC, basically handling the repetitions + prach_mask = is_prach_subframe(&eNB->frame_parms,proc->frame_prach_br,proc->subframe_prach_br); + + for (i=0; i<4; i++) { + if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i]==1) && + ((prach_mask&(1<<(i+1))) > 0)) { // check that prach CE level is active now + + // if first reception in group of repetitions store frame for later (in RA-RNTI for Msg2) + if (eNB->prach_vars_br.repetition_number[i]==0) eNB->prach_vars_br.first_frame[i]=proc->frame_prach_br; + + // increment repetition number + eNB->prach_vars_br.repetition_number[i]++; + // do basic PRACH reception + rx_prach0(eNB,ru,proc->frame_prach, proc->subframe_prach_br, + max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); + + // if last repetition, clear counter + if (eNB->prach_vars_br.repetition_number[i] == eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[i]) { + eNB->prach_vars_br.repetition_number[i]=0; + } + } + } /* for i ... */ + } /* else br_flag == 0 */ +} + +void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int br_flag) { + uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4],avg_preamble_energy[4]; + RU_t *ru; + int aa=0; + int ru_aa; + + for (int i=0; inum_RU; i++) { + ru=eNB->RU_list[i]; + + for (ru_aa=0,aa=0; ru_aanb_rx; ru_aa++,aa++) { + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + int ce_level; + + if (br_flag==1) + for (ce_level=0; ce_level<4; ce_level++) + eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[i]->prach_rxsigF_br[ce_level][ru_aa]; + } + } + + // run PRACH detection for CE-level 0 only for now when br_flag is set + ocp_rx_prach(eNB, + proc, + eNB->RU_list[0], + &max_preamble[0], + &max_preamble_energy[0], + &max_preamble_delay[0], + &avg_preamble_energy[0], + proc->frame_prach, + 0 + ,br_flag + ); + LOG_D(PHY,"RACH detection index 0: max preamble: %u, energy: %u, delay: %u, avg energy: %u\n", + max_preamble[0], + max_preamble_energy[0], + max_preamble_delay[0], + avg_preamble_energy[0] + ); + + if (br_flag==1) { + int prach_mask; + prach_mask = is_prach_subframe (&eNB->frame_parms, proc->frame_prach_br, proc->subframe_prach_br); + eNB->UL_INFO.rach_ind_br.rach_indication_body.preamble_list = eNB->preamble_list_br; + int ind = 0; + int ce_level = 0; + /* Save for later, it doesn't work + for (int ind=0,ce_level=0;ce_level<4;ce_level++) { + + if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[ce_level]==1)&& + (prach_mask&(1<<(1+ce_level)) > 0) && // prach is active and CE level has finished its repetitions + (eNB->prach_vars_br.repetition_number[ce_level]== + eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level])) { + + */ + + if (eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[0] == 1) { + if ((eNB->prach_energy_counter == 100) && (max_preamble_energy[0] > eNB->measurements.prach_I0 + eNB->prach_DTX_threshold_emtc[0])) { + eNB->UL_INFO.rach_ind_br.rach_indication_body.number_of_preambles++; + eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind]; // + eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind]; + // note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4 + eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + proc->subframe_prach + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); + eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is + eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1 + ce_level; // CE Level + LOG_I (PHY, "Filling NFAPI indication for RACH %d CELevel %d (mask %x) : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + ind, + ce_level, + prach_mask, + eNB->preamble_list_br[ind].preamble_rel8.timing_advance, + eNB->preamble_list_br[ind].preamble_rel8.preamble, eNB->preamble_list_br[ind].preamble_rel8.rnti, eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type); + } + } + + /* + ind++; + } + } */// ce_level + } else if ((eNB->prach_energy_counter == 100) && + (max_preamble_energy[0] > eNB->measurements.prach_I0+eNB->prach_DTX_threshold)) { + LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", + eNB->Mod_id, + eNB->CC_id, + proc->frame_prach, + proc->subframe_prach, + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_energy[0]%10, + max_preamble_delay[0]); + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 1; + eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = &eNB->preamble_list[0]; + eNB->UL_INFO.rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG; + eNB->UL_INFO.rach_ind.header.message_id = NFAPI_RACH_INDICATION; + eNB->UL_INFO.rach_ind.sfn_sf = proc->frame_prach<<4 | proc->subframe_prach; + eNB->preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG; + eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0]; + eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0]; + eNB->preamble_list[0].preamble_rel8.rnti = 1+proc->subframe_prach; // note: fid is implicitly 0 here + eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0; + eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is + + if (NFAPI_MODE==NFAPI_MODE_PNF) { // If NFAPI PNF then we need to send the message to the VNF + LOG_D(PHY,"Filling NFAPI indication for RACH : SFN_SF:%d TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + NFAPI_SFNSF2DEC(eNB->UL_INFO.rach_ind.sfn_sf), + eNB->preamble_list[0].preamble_rel8.timing_advance, + eNB->preamble_list[0].preamble_rel8.preamble, + eNB->preamble_list[0].preamble_rel8.rnti, + eNB->preamble_list[0].preamble_rel13.rach_resource_type); + oai_nfapi_rach_ind(&eNB->UL_INFO.rach_ind); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 0; + } + + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + } // max_preamble_energy > prach_I0 + 100 + else { + eNB->measurements.prach_I0 = ((eNB->measurements.prach_I0*900)>>10) + ((avg_preamble_energy[0]*124)>>10); + + if (eNB->prach_energy_counter < 100) + eNB->prach_energy_counter++; + } +} // else br_flag + +void prach_eNB(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int frame,int subframe) { + // check if we have to detect PRACH first + if (is_prach_subframe(&eNB->frame_parms, frame,subframe)>0) { + prach_procedures_ocp(eNB, proc, 0); + prach_procedures_ocp(eNB, proc, 1); + } +} + +static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) { + AssertFatal( eNB !=NULL, ""); + + if (NFAPI_MODE==NFAPI_MODE_PNF) { + // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick + //add_subframe(&frame, &subframe, 4); + //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); + oai_subframe_ind(proc->frame_rx, proc->subframe_rx); + } + + AssertFatal( !(NFAPI_MODE==NFAPI_MODE_PNF && + eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0), ""); + prach_eNB(eNB,proc,proc->frame_rx,proc->subframe_rx); + release_UE_in_freeList(eNB->Mod_id); + + // UE-specific RX processing for subframe n + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX(eNB, proc); + } + + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.frame = proc->frame_rx; + eNB->UL_INFO.subframe = proc->subframe_rx; + eNB->UL_INFO.module_id = eNB->Mod_id; + eNB->UL_INFO.CC_id = eNB->CC_id; + eNB->if_inst->UL_indication(&eNB->UL_INFO, proc); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + phy_procedures_eNB_TX(eNB, proc, 1); + return(0); +} + +void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { + LTE_DL_FRAME_PARMS *fp = ru->frame_parms; + void *rxp[ru->nb_rx]; + unsigned int rxs; + int i; + openair0_timestamp ts=0, timestamp_rx; + static openair0_timestamp old_ts=0; + + for (i=0; inb_rx; i++) + //receive in the next slot + rxp[i] = (void *)&ru->common.rxdata[i][((proc->subframe_rx+1)%10)*fp->samples_per_tti]; + + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &ts, + rxp, + fp->samples_per_tti, + ru->nb_rx); + timestamp_rx = ts-ru->ts_offset; + + // AssertFatal(rxs == fp->samples_per_tti, + // "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); + if(rxs != fp->samples_per_tti) { + LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); +#if defined(USRP_REC_PLAY) + exit_fun("Exiting IQ record/playback"); +#else + //exit_fun( "problem receiving samples" ); + LOG_E(PHY, "problem receiving samples"); +#endif + } + + if (old_ts != 0 && timestamp_rx - old_ts != fp->samples_per_tti) { + LOG_E(HW,"impossible shift in rx stream, rx: %ld, previous rx distance: %ld, should be %d\n", timestamp_rx, proc->timestamp_rx - old_ts, fp->samples_per_tti); + //ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); + //proc->timestamp_rx = ts-ru->ts_offset; + } + + old_ts=timestamp_rx; + setAllfromTS(timestamp_rx, proc); +} + +void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { + LTE_DL_FRAME_PARMS *fp = ru->frame_parms; + void *txp[ru->nb_tx]; + int i; + lte_subframe_t SF_type = subframe_select(fp,proc->subframe_tx%10); + lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10); + int sf_extension = 0; + + if ((SF_type == SF_DL) || + (SF_type == SF_S)) { + int siglen=fp->samples_per_tti,flags=1; + + if (SF_type == SF_S) { + /* end_of_burst_delay is used to stop TX only "after a while". + * If we stop right after effective signal, with USRP B210 and + * B200mini, we observe a high EVM on the S subframe (on the + * PSS). + * A value of 400 (for 30.72MHz) solves this issue. This is + * the default. + */ + siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + + (fp->dl_symbols_in_S_subframe - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples) + + ru->end_of_burst_delay; + flags=3; // end of burst + } + + if (fp->frame_type == TDD && + SF_type == SF_DL && + prevSF_type == SF_UL) { + flags = 2; // start of burst + sf_extension = ru->sf_extension; + } + +#if defined(__x86_64) || defined(__i386__) +#ifdef __AVX2__ + sf_extension = (sf_extension)&0xfffffff8; +#else + sf_extension = (sf_extension)&0xfffffffc; +#endif +#elif defined(__arm__) + sf_extension = (sf_extension)&0xfffffffc; +#endif + + for (i=0; inb_tx; i++) + txp[i] = (void *)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension]; + + /* add fail safe for late command end */ + // prepare tx buffer pointers + ru->rfdevice.trx_write_func(&ru->rfdevice, + proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); + LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, subframe %d\n",ru->idx, + (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->subframe_tx); + } + + return; +} + +static void *ru_thread( void *param ) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + RU_t *ru = (RU_t *)param; + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + + if (ru->if_south == LOCAL_RF) { // configure RF parameters only + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + phy_init_RU(ru); + init_rf(ru); + } + + AssertFatal(setup_RU_buffers(ru)==0, "Exiting, cannot initialize RU Buffers\n"); + LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); + wait_sync("ru_thread"); + + // Start RF device if any + if (ru->rfdevice.trx_start_func(&ru->rfdevice) != 0) + LOG_E(HW,"Could not start the RF device\n"); + else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + while (!oai_exit) { + // synchronization on input FH interface, acquire signals/data and block + rx_rf(ru, &L1proc); + // do RX front-end processing (frequency-shift, dft) if needed + fep_full(ru, L1proc.subframe_rx); + + // At this point, all information for subframe has been received on FH interface + // If this proc is to provide synchronization, do so + // Fixme: not used + // wakeup_slaves(proc); + for (int i=0; inum_eNB; i++) { + char string[20]; + sprintf(string,"Incoming RU %d",ru->idx); + + if (rxtx(ru->eNB_list[i],&L1proc,string) < 0) + LOG_E(PHY,"eNB %d CC_id %d failed during execution\n", + ru->eNB_list[i]->Mod_id,ru->eNB_list[i]->CC_id); + } + + // do TX front-end processing if needed (precoding and/or IDFTs) + feptx_prec(ru, L1proc.frame_tx, L1proc.subframe_tx); + // do OFDM if needed + feptx_ofdm(ru, L1proc.frame_tx, L1proc.subframe_tx); + // do outgoing fronthaul (south) if needed + ocp_tx_rf(ru, &L1proc); + } + + LOG_W(PHY,"Exiting ru_thread \n"); + ru->rfdevice.trx_end_func(&ru->rfdevice); + LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); + return NULL; +} + +int init_rf(RU_t *ru) { + char name[256]; + pthread_getname_np(pthread_self(),name, 255); + pthread_setname_np(pthread_self(),"UHD for OAI"); + int ret=openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + pthread_setname_np(pthread_self(),name); + return ret; +} + +void init_RU(char *rf_config_file, int send_dmrssync) { + RU_t *ru; + PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL; + int i; + int CC_id; + // read in configuration file) + LOG_I(PHY,"configuring RU from file\n"); + 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()); + + if (RC.nb_CC != 0) + for (i=0; inum_RU=0; + + LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); + + for (int ru_id=0; ru_idrf_config_file = rf_config_file; + ru->idx = ru_id; + ru->ts_offset = 0; + + if (ru->is_slave == 1) { + ru->in_synch = 0; + ru->generate_dmrs_sync = 0; + } else { + ru->in_synch = 1; + ru->generate_dmrs_sync=send_dmrssync; + } + + ru->cmd = EMPTY; + ru->south_out_cnt= 0; + + // ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0; + if (ru->generate_dmrs_sync == 1) { + generate_ul_ref_sigs(); + ru->dmrssync = (int16_t *)malloc16_clear(ru->frame_parms->ofdm_symbol_size*2*sizeof(int16_t)); + } + + ru->wakeup_L1_sleeptime = 2000; + ru->wakeup_L1_sleep_cnt_max = 3; + + if (ru->num_eNB > 0) { + LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", + __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file); + AssertFatal(ru->eNB_list[0], "ru->eNB_list is not initialized\n"); + } else { + LOG_E(PHY,"Wrong data model, assigning eNB 0, carrier 0 to RU 0\n"); + ru->eNB_list[0] = RC.eNB[0][0]; + ru->num_eNB=1; + } + + eNB0 = ru->eNB_list[0]; + // datamodel error in regular OAI: a RU uses one single eNB carrier parameters! + ru->frame_parms = &eNB0->frame_parms; + + for (i=0; inum_eNB; i++) { + eNB0 = ru->eNB_list[i]; + int ruIndex=eNB0->num_RU++; + eNB0->RU_list[ruIndex] = ru; + } + } // for ru_id +} + +void stop_RU(int nb_ru) { + for (int inst = 0; inst < nb_ru; inst++) { + LOG_I(PHY, "Stopping RU %d processing threads\n", inst); + kill_RU_proc(RC.ru[inst]); + } +} + +/* --------------------------------------------------------*/ +/* from here function to use configuration module */ +static int DEFBFW[] = {0x00007fff}; +void RCconfig_RU(void) { + paramdef_t RUParams[] = RUPARAMS_DESC; + paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; + config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL); + + if ( RUParamList.numelt == 0 ) { + LOG_W(PHY, "Calling RCconfig_RU while no ru\n"); + RC.nb_RU = 0; + return; + } // setting != NULL + + if ( RC.ru != NULL ) { + LOG_W(PHY, "Calling RCconfig_RU twice (nb ru=%d), ignoring the second call data structure is %p\n", + RUParamList.numelt,RC.ru); + return; + } + + RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); + + for (int j = 0; j < RC.nb_RU; j++) { + RC.ru[j] = (RU_t *)calloc(sizeof(RU_t), 1); + RC.ru[j]->idx = j; + LOG_I(PHY,"Creating RC.ru[%d]:%p\n", j, RC.ru[j]); + RC.ru[j]->if_timing = synch_to_ext_device; + paramdef_t *vals=RUParamList.paramarray[j]; + + if (RC.nb_L1_inst >0) + RC.ru[j]->num_eNB = vals[RU_ENB_LIST_IDX].numelt; + else + RC.ru[j]->num_eNB = 0; + + for (int i=0; inum_eNB; i++) + RC.ru[j]->eNB_list[i] = RC.eNB[vals[RU_ENB_LIST_IDX].iptr[i]][0]; + + if (config_isparamset(vals, RU_SDR_ADDRS)) { + RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(vals[RU_SDR_ADDRS].strptr)); + } + + if (config_isparamset(vals, RU_SDR_CLK_SRC)) { + char *paramVal=*(vals[RU_SDR_CLK_SRC].strptr); + LOG_D(PHY, "RU clock source set as %s\n", paramVal); + + if (strcmp(paramVal, "internal") == 0) { + RC.ru[j]->openair0_cfg.clock_source = internal; + } else if (strcmp(paramVal, "external") == 0) { + RC.ru[j]->openair0_cfg.clock_source = external; + } else if (strcmp(paramVal, "gpsdo") == 0) { + RC.ru[j]->openair0_cfg.clock_source = gpsdo; + } else { + LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", paramVal); + } + } + + if (strcmp(*(vals[RU_LOCAL_RF_IDX].strptr), "yes") == 0) { + if ( !(config_isparamset(vals,RU_LOCAL_IF_NAME_IDX)) ) { + RC.ru[j]->if_south = LOCAL_RF; + RC.ru[j]->function = eNodeB_3GPP; + LOG_I(PHY, "Setting function for RU %d to eNodeB_3GPP\n",j); + } else { + RC.ru[j]->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); + } + + RC.ru[j]->max_pdschReferenceSignalPower = *(vals[RU_MAX_RS_EPRE_IDX].uptr);; + RC.ru[j]->max_rxgain = *(vals[RU_MAX_RXGAIN_IDX].uptr); + RC.ru[j]->num_bands = vals[RU_BAND_LIST_IDX].numelt; + /* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */ + RC.ru[j]->sf_extension = *(vals[RU_SF_EXTENSION_IDX].uptr); + RC.ru[j]->end_of_burst_delay = *(vals[RU_END_OF_BURST_DELAY_IDX].uptr); + + for (int i=0; inum_bands; i++) RC.ru[j]->band[i] = vals[RU_BAND_LIST_IDX].iptr[i]; + } else { + LOG_I(PHY,"RU %d: Transport %s\n",j,*(vals[RU_TRANSPORT_PREFERENCE_IDX].strptr)); + RC.ru[j]->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); + } /* strcmp(local_rf, "yes") != 0 */ + + RC.ru[j]->nb_tx = *(vals[RU_NB_TX_IDX].uptr); + RC.ru[j]->nb_rx = *(vals[RU_NB_RX_IDX].uptr); + RC.ru[j]->att_tx = *(vals[RU_ATT_TX_IDX].uptr); + RC.ru[j]->att_rx = *(vals[RU_ATT_RX_IDX].uptr); + }// j=0..num_rus + + return; +} + + +static void get_options(void) { + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + get_common_options(SOFTMODEM_ENB_BIT); + CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); + + if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) { + memset((void *)&RC,0,sizeof(RC)); + /* Read RC configuration file */ + RCConfig(); + NB_eNB_INST = RC.nb_inst; + printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU); + + if (!IS_SOFTMODEM_NONBIOT) { + load_NB_IoT(); + printf(" nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n", + RC.nb_nb_iot_rrc_inst, RC.nb_nb_iot_L1_inst, RC.nb_nb_iot_macrlc_inst); + } else { + printf("All Nb-IoT instances disabled\n"); + RC.nb_nb_iot_rrc_inst=RC.nb_nb_iot_L1_inst=RC.nb_nb_iot_macrlc_inst=0; + } + } +} + +void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { + int CC_id; + + for (CC_id=0; CC_idframe_type = FDD; + frame_parms[CC_id]->tdd_config = 3; + frame_parms[CC_id]->tdd_config_S = 0; + frame_parms[CC_id]->N_RB_DL = 100; + frame_parms[CC_id]->N_RB_UL = 100; + frame_parms[CC_id]->Ncp = NORMAL; + frame_parms[CC_id]->Ncp_UL = NORMAL; + frame_parms[CC_id]->Nid_cell = 0; + frame_parms[CC_id]->num_MBSFN_config = 0; + frame_parms[CC_id]->nb_antenna_ports_eNB = 1; + frame_parms[CC_id]->nb_antennas_tx = 1; + frame_parms[CC_id]->nb_antennas_rx = 1; + frame_parms[CC_id]->nushift = 0; + frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth; + frame_parms[CC_id]->phich_config_common.phich_duration = normal; + // UL RS Config + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; + // downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31. + // downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0]; + // downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0]; + // downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0]; + //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); + frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0]; + } +} + +void init_pdcp(void) { + if (!NODE_IS_DU(RC.rrc[0]->node_type)) { + pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + + if (IS_SOFTMODEM_NOS1) + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; + + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT; + + if ( split73!=SPLIT73_DU) + pdcp_module_init(pdcp_initmask); + + if (NODE_IS_CU(RC.rrc[0]->node_type)) { + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); + } else { + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); + } + } else { + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); + } +} + +static void wait_nfapi_init(char *thread_name) { + printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name); + pthread_mutex_lock( &nfapi_sync_mutex ); + + while (nfapi_sync_var<0) + pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex ); + + pthread_mutex_unlock(&nfapi_sync_mutex); + printf( "NFAPI: got sync (%s)\n", thread_name); +} + +void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) { + LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n", + itti_get_task_name(from), from, itti_get_task_name(to), to); + MessageDef *msg; + msg = itti_alloc_new_message (from, TERMINATE_MESSAGE); + itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); +} + +int stop_L1L2(module_id_t enb_id) { + LOG_W(ENB_APP, "stopping lte-softmodem\n"); + + if (!RC.ru) { + LOG_UI(ENB_APP, "no RU configured\n"); + return -1; + } + + /* these tasks need to pick up new configuration */ + terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB); + oai_exit = 1; + LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id); + kill_RU_proc(RC.ru[enb_id]); + LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id); + kill_eNB_proc(enb_id); + oai_exit = 0; + + for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) { + free_transport(RC.eNB[enb_id][cc_id]); + phy_free_lte_eNB(RC.eNB[enb_id][cc_id]); + } + + phy_free_RU(RC.ru[enb_id]); + free_lte_top(); + return 0; +} + +/* + * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2() + */ +int restart_L1L2(module_id_t enb_id) { + RU_t *ru = RC.ru[enb_id]; + MessageDef *msg_p = NULL; + LOG_W(ENB_APP, "restarting lte-softmodem\n"); + /* block threads */ + pthread_mutex_lock(&sync_mutex); + sync_var = -1; + pthread_mutex_unlock(&sync_mutex); + RC.ru_mask |= (1 << ru->idx); + /* copy the changed frame parameters to the RU */ + /* TODO this should be done for all RUs associated to this eNB */ + memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS)); + /* reset the list of connected UEs in the MAC, since in this process with + * loose all UEs (have to reconnect) */ + init_UE_info(&RC.mac[enb_id]->UE_info); + LOG_I(ENB_APP, "attempting to create ITTI tasks\n"); + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); + /* pass a reconfiguration request which will configure everything down to + * RC.eNB[i][j]->frame_parms, too */ + msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ); + RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; + itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); + /* TODO XForms might need to be restarted, but it is currently (09/02/18) + * broken, so we cannot test it */ + init_RU_proc(ru); + ru->rf_map.card = 0; + ru->rf_map.chain = 0; /* CC_id + chain_offset;*/ + init_eNB_afterRU(); + printf("Sending sync to all threads\n"); + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); + return 0; +} + +int main ( int argc, char **argv ) { + int i; + int CC_id = 0; + int node_type = ngran_eNB; + AssertFatal(load_configmodule(argc,argv,0), "[SOFTMODEM] Error, configuration module init failed\n"); + logInit(); + printf("Reading in command-line options\n"); + get_options (); + AssertFatal(!CONFIG_ISFLAGSET(CONFIG_ABORT),"Getting configuration failed\n"); + EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; +#if T_TRACER + T_Config_Init(); +#endif + configure_linux(); + cpuf=get_cpu_freq_GHz(); + set_taus_seed (0); + + if (opp_enabled ==1) + reset_opp_meas(); + + itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + init_opt(); +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); + + /* Read configuration */ + if (RC.nb_inst > 0) { + // Allocate memory from RC variable + read_config_and_init(); + } else { + printf("RC.nb_inst = 0, Initializing L1\n"); + RCconfig_L1(); + } + + /* We need to read RU configuration before FlexRAN starts so it knows what + * splits to report. Actual RU start comes later. */ + if (RC.nb_RU > 0 && NFAPI_MODE != NFAPI_MODE_VNF) { + 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()); + } + + if ( strlen(get_softmodem_params()->split73) > 0 ) { + char tmp[1024]={0}; + strncpy(tmp,get_softmodem_params()->split73, 1023); + tmp[2]=0; + if ( strncasecmp(tmp,"cu", 2)==0 ) + split73=SPLIT73_CU; + else if ( strncasecmp(tmp,"du", 2)==0 ) + split73=SPLIT73_DU; + else + AssertFatal(false,"split73 syntax: :[:] (string found: %s) \n",get_softmodem_params()->split73); + } + + if (RC.nb_inst > 0) { + /* Start the agent. If it is turned off in the configuration, it won't start */ + for (i = 0; i < RC.nb_inst; i++) { + flexran_agent_start(i); + } + + /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks + * for monolithic/F1 modes */ + init_pdcp(); + AssertFatal(create_tasks(1)==0,"cannot create ITTI tasks\n"); + + for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) { + MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ); + RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; + itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); + } + + node_type = RC.rrc[0]->node_type; + } + + if (RC.nb_inst > 0 && NODE_IS_CU(node_type)) { + protocol_ctxt_t ctxt; + ctxt.module_id = 0 ; + ctxt.instance = 0; + ctxt.rnti = 0; + ctxt.enb_flag = 1; + ctxt.frame = 0; + ctxt.subframe = 0; + pdcp_run(&ctxt); + } + + /* start threads if only L1 or not a CU */ + if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) { + // init UE_PF_PO and mutex lock + pthread_mutex_init(&ue_pf_po_mutex, NULL); + memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs); + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); + + if (NFAPI_MODE!=NFAPI_MONOLITHIC) { + LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n"); + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); + } + + if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF +#if defined(PRE_SCD_THREAD) + init_ru_vnf(); // ru pointer is necessary for pre_scd. +#endif + wait_nfapi_init("main?"); + } + + LOG_I(ENB_APP,"START MAIN THREADS\n"); + // start the main threads + number_of_cards = 1; + printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst); + + if (RC.nb_L1_inst > 0) { + printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", + get_softmodem_params()->single_thread_flag, + get_softmodem_params()->wait_for_sync); + init_eNB(get_softmodem_params()->single_thread_flag, + get_softmodem_params()->wait_for_sync); + } + + for (int x=0; x < RC.nb_L1_inst; x++) + for (int CC_id=0; CC_idproc.L1_proc; + L1proc->threadPool=(tpool_t *)malloc(sizeof(tpool_t)); + L1proc->respEncode=(notifiedFIFO_t *) malloc(sizeof(notifiedFIFO_t)); + L1proc->respDecode=(notifiedFIFO_t *) malloc(sizeof(notifiedFIFO_t)); + + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) + initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true); + else + initTpool("n", L1proc->threadPool, true); + + initNotifiedFIFO(L1proc->respEncode); + initNotifiedFIFO(L1proc->respDecode); + } + } + + printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU); + + // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator. + // but RU thread deals with pre_scd and this is necessary in VNF and simulator. + // some initialization is necessary and init_ru_vnf do this. + if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) { + printf("Initializing RU threads\n"); + init_RU(get_softmodem_params()->rf_config_file, + get_softmodem_params()->send_dmrs_sync); + + for (int ru_id=0; ru_idrf_map.card=0; + RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset); + LOG_I(PHY,"Starting ru_thread %d\n",ru_id); + init_RU_proc(RC.ru[ru_id]); + } + + config_sync_var=0; + + if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF + wait_nfapi_init("main?"); + } + + LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU); + // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration) + printf("ALL RUs ready - init eNBs\n"); + + if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) { + LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n"); + init_eNB_afterRU(); + } else { + LOG_I(ENB_APP,"NFAPI mode - DO NOT call init_eNB_afterRU()\n"); + } + + LOG_UI(ENB_APP,"ALL RUs ready - ALL eNBs ready\n"); + // connect the TX/RX buffers + sleep(1); /* wait for thread activation */ + LOG_I(ENB_APP,"Sending sync to all threads\n"); + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); + config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); + } + + create_tasks_mbms(1); + // wait for end of program + LOG_UI(ENB_APP,"TYPE TO TERMINATE\n"); + // CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file + fflush(stdout); + fflush(stderr); + + // end of CI modifications + //getchar(); + if(IS_SOFTMODEM_DOFORMS) + load_softscope("enb"); + + itti_wait_tasks_end(); + oai_exit=1; + LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit); + // stop threads + + if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) { + if(IS_SOFTMODEM_DOFORMS) + end_forms(); + + LOG_I(ENB_APP,"stopping MODEM threads\n"); + stop_eNB(NB_eNB_INST); + stop_RU(RC.nb_RU); + + /* release memory used by the RU/eNB threads (incomplete), after all + * threads have been stopped (they partially use the same memory) */ + for (int inst = 0; inst < NB_eNB_INST; inst++) { + for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) { + free_transport(RC.eNB[inst][cc_id]); + phy_free_lte_eNB(RC.eNB[inst][cc_id]); + } + } + + for (int inst = 0; inst < RC.nb_RU; inst++) { + phy_free_RU(RC.ru[inst]); + } + + free_lte_top(); + end_configmodule(); + pthread_cond_destroy(&sync_cond); + pthread_mutex_destroy(&sync_mutex); + pthread_cond_destroy(&nfapi_sync_cond); + pthread_mutex_destroy(&nfapi_sync_mutex); + pthread_mutex_destroy(&ue_pf_po_mutex); + + for(int ru_id=0; ru_idrfdevice.trx_end_func) { + RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_end_func = NULL; + } + + if (RC.ru[ru_id]->ifdevice.trx_end_func) { + RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_end_func = NULL; + } + } + } + + terminate_opt(); + logClean(); + printf("Bye.\n"); + return 0; +} diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index b988a96941..e1e2c5b3e4 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -61,10 +61,7 @@ #include "PHY/phy_extern.h" - -#include "LAYER2/MAC/mac.h" -#include "NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" +#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" #include "RRC/LTE/rrc_extern.h" #include "PHY_INTERFACE/phy_interface.h" #include "common/utils/LOG/log_extern.h" @@ -187,8 +184,8 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx); } */ - // Call the scheduler + pthread_mutex_lock(&gNB->UL_INFO_mutex); gNB->UL_INFO.frame = frame_rx; gNB->UL_INFO.slot = slot_rx; @@ -333,7 +330,7 @@ static void *gNB_L1_thread( void *param ) { gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc; //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id]; char thread_name[100]; - + // set default return value // set default return value gNB_thread_rxtx_status = 0; @@ -430,7 +427,7 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot int waitret = 0, ret = 0, time_ns = 1000*1000; struct timespec now, abstime; - + // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1); time_ns = time_ns/gNB->frame_parms.slots_per_subframe; @@ -452,27 +449,27 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0); if (waitret == ETIMEDOUT) { - LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); + LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); - AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); - gNB->proc.RU_mask_tx = 0; - AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); + gNB->proc.RU_mask_tx = 0; + AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); + proc->instance_cnt_RUs = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); + + return(-1); + } - return(-1); - } - for(int i=0; inum_RU; i++) { ru = gNB->RU_list[i]; ru_proc = &ru->proc; - + if (ru_proc->instance_cnt_gNBs == 0) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1); @@ -493,10 +490,10 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs); - LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); + LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); // the thread can now be woken up AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0, - "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); + "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret); } @@ -514,7 +511,7 @@ int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_t AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); - while(L1_proc_tx->instance_cnt == 0){ + while(L1_proc_tx->instance_cnt == 0) { pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex); } @@ -530,7 +527,7 @@ int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_t VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0); - + // the thread can now be woken up // the thread can now be woken up AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n"); @@ -550,11 +547,11 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { int time_ns = 50000; AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret); - for (i=0;inum_RU;i++) { + for (i=0; inum_RU; i++) { if (ru == gNB->RU_list[i]) { if ((proc->RU_mask&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); + LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", + gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); proc->RU_mask |= (1<mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret); if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe - AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); - LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); - return(-1); + AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); + LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); + return(-1); } - + ++L1_proc->instance_cnt; - - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired + // We have just received and processed the common part of a subframe, say n. + // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired // transmitted timestamp of the next TX slot (first). + // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, // we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti, // and proc->slot_tx = proc->slot_rx+sf_ahead @@ -610,7 +607,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { exit_fun( "ERROR pthread_cond_signal" ); return(-1); } - + return(0); } /* @@ -714,9 +711,9 @@ static void* gNB_thread_prach( void* param ) { extern void init_td_thread(PHY_VARS_gNB *); extern void init_te_thread(PHY_VARS_gNB *); -static void* process_stats_thread(void* param) { +static void *process_stats_thread(void *param) { - PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)param; + PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; reset_meas(&gNB->dlsch_encoding_stats); reset_meas(&gNB->dlsch_scrambling_stats); diff --git a/executables/nr-ru.c b/executables/nr-ru.c index da1e241b7a..6a3a25d9f0 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1,41 +1,24 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - -*******************************************************************************/ - -/*! \file lte-enb.c - * \brief Top-level threads for eNodeB - * \author R. Knopp, F. Kaltenberger, Navid Nikaein - * \date 2012 - * \version 0.1 - * \company Eurecom - * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr - * \note - * \warning +/* + * 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 */ + #define _GNU_SOURCE #include #include @@ -73,9 +56,8 @@ #include "SCHED/sched_eNB.h" #include "SCHED_NR/sched_nr.h" -#include "LAYER2/MAC/mac.h" #include "NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" + #include "RRC/LTE/rrc_extern.h" #include "PHY_INTERFACE/phy_interface.h" @@ -94,7 +76,7 @@ unsigned short config_frames[4] = {2,9,11,13}; static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; static int DEFBFW[] = {0x00007fff}; - + //static int DEFNRBANDS[] = {7}; //static int DEFGNBS[] = {0}; @@ -714,7 +696,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } -void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_scf_t *cfg = &ru->config; @@ -885,7 +867,7 @@ void *ru_thread_prach( void *param ) { 0,0 ); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; } @@ -1112,16 +1094,16 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { } } else if(N_RB == 106) { if (fp->threequarter_fs) { - cfg->sample_rate=46.08e6; - cfg->samples_per_frame = 460800; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; } else { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; } } else { AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); @@ -1285,7 +1267,7 @@ void *ru_stats_thread(void *param) { if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); - if (ru->feptx_ofdm){ + if (ru->feptx_ofdm) { print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL); print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL); print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); @@ -1294,7 +1276,7 @@ void *ru_stats_thread(void *param) { if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); - print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); + print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); if (ru->fh_north_out) { print_meas(&ru->compression,"compression",NULL,NULL); print_meas(&ru->transport,"transport",NULL,NULL); @@ -1425,7 +1407,7 @@ void *ru_thread_tx( void *param ) { L1_proc->instance_cnt_RUs = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, - "ERROR pthread_cond_signal for gNB_L1_thread\n"); + "ERROR pthread_cond_signal for gNB_L1_thread\n"); } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); @@ -2350,9 +2332,27 @@ void RCconfig_RU(void) } } else { - RC.ru[j]->openair0_cfg.clock_source = unset; + RC.ru[j]->openair0_cfg.clock_source = unset; } + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { + if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) { + RC.ru[j]->openair0_cfg.time_source = internal; + LOG_D(PHY, "RU time source set as internal\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) { + RC.ru[j]->openair0_cfg.time_source = external; + LOG_D(PHY, "RU time source set as external\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) { + RC.ru[j]->openair0_cfg.time_source = gpsdo; + LOG_D(PHY, "RU time source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); + } + } + else { + RC.ru[j]->openair0_cfg.time_source = unset; + } + if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { RC.ru[j]->if_south = LOCAL_RF; diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 59aa229b1a..054b02dd0d 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -49,8 +49,6 @@ #include "PHY/phy_vars.h" #include "SCHED/sched_common_vars.h" #include "LAYER2/MAC/mac_vars.h" -#include "LAYER2/MAC/mac.h" -#include "LAYER2/MAC/mac_proto.h" #include "RRC/LTE/rrc_vars.h" #include "PHY_INTERFACE/phy_interface_vars.h" #include "gnb_config.h" @@ -108,7 +106,7 @@ static int wait_for_sync = 0; unsigned int mmapped_dma=0; int single_thread_flag=1; -static int8_t threequarter_fs=0; +int8_t threequarter_fs=0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; @@ -171,6 +169,10 @@ uint32_t target_ul_mcs = 20; uint32_t timing_advance = 0; uint64_t num_missed_slots=0; // counter for the number of missed slots +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} extern void reset_opp_meas(void); extern void print_opp_meas(void); @@ -725,13 +727,9 @@ int restart_L1L2(module_id_t gnb_id) { memcpy(&ru->nr_frame_parms, &RC.gNB[gnb_id]->frame_parms, sizeof(NR_DL_FRAME_PARMS)); set_function_spec_param(RC.ru[gnb_id]); LOG_I(GNB_APP, "attempting to create ITTI tasks\n"); - - if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) { - LOG_E(RRC, "Create task for RRC eNB failed\n"); - return -1; - } else { - LOG_I(RRC, "Re-created task for RRC gNB successfully\n"); - } + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) { LOG_E(PDCP, "Create task for L2L1 failed\n"); @@ -774,23 +772,23 @@ static void wait_nfapi_init(char *thread_name) { void init_pdcp(void) { //if (!NODE_IS_DU(RC.rrc[0]->node_type)) { - pdcp_layer_init(); - uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? - (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; - if (IS_SOFTMODEM_NOS1){ - printf("IS_SOFTMODEM_NOS1 option enabled \n"); - pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; - } + if (IS_SOFTMODEM_NOS1) { + printf("IS_SOFTMODEM_NOS1 option enabled \n"); + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; + } - pdcp_module_init(pdcp_initmask); + pdcp_module_init(pdcp_initmask); - /*if (NODE_IS_CU(RC.rrc[0]->node_type)) { - pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); - } else {*/ - pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); - pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); - //} + /*if (NODE_IS_CU(RC.rrc[0]->node_type)) { + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); + } else {*/ + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); + //} /*} else { pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); }*/ @@ -848,7 +846,7 @@ int main( int argc, char **argv ) MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); -init_opt(); + init_opt(); #ifdef PDCP_USE_NETLINK @@ -865,7 +863,7 @@ if(!IS_SOFTMODEM_NOS1) LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); if(IS_SOFTMODEM_NOS1) - init_pdcp(); + init_pdcp(); if (RC.nb_nr_inst > 0) { // don't create if node doesn't connect to RRC/S1/GTP @@ -995,27 +993,27 @@ if(!IS_SOFTMODEM_NOS1) printf("oai_exit=%d\n",oai_exit); // stop threads -/*#ifdef XFORMS + /*#ifdef XFORMS - printf("waiting for XFORMS thread\n"); + printf("waiting for XFORMS thread\n"); - if (do_forms==1) { - pthread_join(forms_thread,&status); - fl_hide_form(form_stats->stats_form); - fl_free_form(form_stats->stats_form); + if (do_forms==1) { + pthread_join(forms_thread,&status); + fl_hide_form(form_stats->stats_form); + fl_free_form(form_stats->stats_form); - fl_hide_form(form_stats_l2->stats_form); - fl_free_form(form_stats_l2->stats_form); + fl_hide_form(form_stats_l2->stats_form); + fl_free_form(form_stats_l2->stats_form); - for(UE_id=0; UE_idphy_scope_gNB); - fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB); - } - } - } + for(UE_id=0; UE_idphy_scope_gNB); + fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB); + } + } + } -#endif*/ + #endif*/ printf("stopping MODEM threads\n"); // cleanup stop_gNB(NB_gNB_INST); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 514d5f0239..30ce657edb 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -481,6 +481,23 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { pdcp_run(&ctxt); } } + + // no UL for now + // no UL for now + /* + if (UE->mac_enabled==1) { + // trigger L2 to run ue_scheduler thru IF module + // [TODO] mapping right after NR initial sync + if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) { + UE->ul_indication.module_id = 0; + UE->ul_indication.gNB_index = 0; + UE->ul_indication.cc_id = 0; + UE->ul_indication.frame = proc->frame_rx; + UE->ul_indication.slot = proc->nr_tti_rx; + UE->if_inst->ul_indication(&UE->ul_indication); + } + } + */ } /*! @@ -519,9 +536,9 @@ void UE_processing(void *arg) { // then timing advance is processed and set to be applied in the next UL transmission */ if (UE->mac_enabled == 1) { - if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot){ + if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) { LOG_D(PHY,"Applying timing advance -- frame %d -- slot %d\n", frame_tx, slot_tx); - + //if (nfapi_mode!=3){ //if (nfapi_mode!=3){ nr_process_timing_advance(UE->Mod_id, UE->CC_id, ul_time_alignment->ta_command, numerology, bwp_ul_NB_RB); ul_time_alignment->ta_frame = -1; @@ -603,8 +620,8 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { - LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); - void *dummy_tx[UE->frame_parms.nb_antennas_tx]; + LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); + void *dummy_tx[UE->frame_parms.nb_antennas_tx]; *timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms); for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { @@ -761,7 +778,7 @@ void *UE_thread(void *arg) { #ifdef OAI_ADRV9371_ZC706 /*uint32_t total_gain_dB_prev = 0; if (total_gain_dB_prev != UE->rx_total_gain_dB) { - total_gain_dB_prev = UE->rx_total_gain_dB; + total_gain_dB_prev = UE->rx_total_gain_dB; openair0_cfg[0].rx_gain[0] = UE->rx_total_gain_dB; UE->rfdevice.trx_set_gains_func(&UE->rfdevice,&openair0_cfg[0]); }*/ diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index d5c34fc728..85e7f911f9 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -47,7 +47,6 @@ #include "PHY/NR_REFSIG/nr_mod_table.h" #include "LAYER2/MAC/mac_vars.h" -#include "LAYER2/MAC/mac_proto.h" #include "RRC/LTE/rrc_vars.h" #include "PHY_INTERFACE/phy_interface_vars.h" #include "openair1/SIMULATION/TOOLS/sim.h" @@ -127,7 +126,6 @@ volatile int start_eNB = 0; volatile int start_UE = 0; volatile int oai_exit = 0; -static clock_source_t clock_source = unset; int single_thread_flag=1; static double snr_dB=20; @@ -215,7 +213,7 @@ int emulate_rf = 0; tpool_t *Tpool; #ifdef UE_DLSCH_PARALLELISATION -tpool_t *Tpool_dl; + tpool_t *Tpool_dl; #endif @@ -311,8 +309,8 @@ static void *scope_thread(void *arg) { while (!oai_exit) { phy_scope_nrUE(form_nrue[0], - PHY_vars_UE_g[0][0], - 0,0,1); + PHY_vars_UE_g[0][0], + 0,0,1); usleep(100*1000); } @@ -383,9 +381,9 @@ static void get_options(void) { int tddflag=0, nonbiotflag, vcdflag=0; char *loopfile=NULL; int dumpframe=0; - //uint32_t noS1; //uint32_t nokrnmod; + //uint32_t nokrnmod; paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC_UE ; config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); @@ -529,12 +527,12 @@ void init_openair0(void) { else { openair0_cfg[card].sample_rate=122.88e6; openair0_cfg[card].samples_per_frame = 1228800; - } + } } else { LOG_E(PHY,"Unsupported numerology!\n"); exit(-1); } - }else if(frame_parms[0]->N_RB_DL == 273) { + } else if(frame_parms[0]->N_RB_DL == 273) { if (numerology==1) { if (frame_parms[0]->threequarter_fs) { AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); @@ -542,12 +540,12 @@ void init_openair0(void) { else { openair0_cfg[card].sample_rate=122.88e6; openair0_cfg[card].samples_per_frame = 1228800; - } + } } else { LOG_E(PHY,"Unsupported numerology!\n"); exit(-1); } - }else if(frame_parms[0]->N_RB_DL == 106) { + } else if(frame_parms[0]->N_RB_DL == 106) { if (numerology==0) { if (frame_parms[0]->threequarter_fs) { openair0_cfg[card].sample_rate=23.04e6; @@ -556,15 +554,15 @@ void init_openair0(void) { openair0_cfg[card].sample_rate=30.72e6; openair0_cfg[card].samples_per_frame = 307200; } - } else if (numerology==1) { + } else if (numerology==1) { if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=46.08e6; - openair0_cfg[card].samples_per_frame = 460800; + openair0_cfg[card].sample_rate=46.08e6; + openair0_cfg[card].samples_per_frame = 460800; } else { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 614400; - } + openair0_cfg[card].sample_rate=61.44e6; + openair0_cfg[card].samples_per_frame = 614400; + } } else if (numerology==2) { openair0_cfg[card].sample_rate=122.88e6; openair0_cfg[card].samples_per_frame = 1228800; @@ -597,7 +595,8 @@ void init_openair0(void) { PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); openair0_cfg[card].Mod_id = 0; openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; - openair0_cfg[card].clock_source = clock_source; + openair0_cfg[card].clock_source = get_softmodem_params()->clock_source; + openair0_cfg[card].time_source = get_softmodem_params()->timing_source; openair0_cfg[card].tx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx); openair0_cfg[card].rx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); @@ -639,7 +638,7 @@ void init_pdcp(void) { pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT; /*if (rlc_module_init() != 0) { - LOG_I(RLC, "Problem at RLC initiation \n"); + LOG_I(RLC, "Problem at RLC initiation \n"); } pdcp_layer_init(); nr_ip_over_LTE_DRB_preconfiguration();*/ @@ -649,6 +648,11 @@ void init_pdcp(void) { LOG_I(PDCP, "Before getting out from init_pdcp() \n"); } +// Stupid function addition because UE itti messages queues definition is common with eNB +void *rrc_enb_process_msg(void *notUsed) { + return NULL; +} + int main( int argc, char **argv ) { //uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; @@ -676,12 +680,12 @@ int main( int argc, char **argv ) { set_taus_seed (0); tpool_t pool; Tpool = &pool; - char params[]="-1,-1"; + char params[]="-1,-1"; initTpool(params, Tpool, false); #ifdef UE_DLSCH_PARALLELISATION tpool_t pool_dl; Tpool_dl = &pool_dl; - char params_dl[]="-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1"; + char params_dl[]="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"; initTpool(params_dl, Tpool_dl, false); #endif cpuf=get_cpu_freq_GHz(); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index a5de840258..43b921001a 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -58,7 +58,6 @@ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_PARAMS_DESC_UE { \ - {"clock-source", CONFIG_HLP_EXCCLK, 0, iptr:&clock_source, defintval:0, TYPE_INT, 0}, \ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index f714fa2bd4..04a58413b5 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -81,8 +81,8 @@ char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr) { } void get_common_options(uint32_t execmask) { - uint32_t online_log_messages; - uint32_t glog_level ; + uint32_t online_log_messages=0; + uint32_t glog_level=0 ; uint32_t start_telnetsrv = 0; uint32_t noS1 = 0, nokrnmod = 0, nonbiot = 0; uint32_t rfsim = 0, basicsim = 0, do_forms = 0; @@ -145,27 +145,27 @@ void get_common_options(uint32_t execmask) { if(worker_config != NULL) set_worker_conf(worker_config); } void softmodem_printresources(int sig, telnet_printfunc_t pf) { - struct rusage usage; - struct timespec stop; + struct rusage usage; + struct timespec stop; - clock_gettime(CLOCK_BOOTTIME, &stop); + clock_gettime(CLOCK_BOOTTIME, &stop); - uint64_t elapse = (stop.tv_sec - start.tv_sec) ; // in seconds + uint64_t elapse = (stop.tv_sec - start.tv_sec) ; // in seconds - int st = getrusage(RUSAGE_SELF,&usage); - if (!st) { - pf("\nRun time: %lluh %llus\n",(unsigned long long)elapse/3600,(unsigned long long)(elapse - (elapse/3600))); - pf("\tTime executing user inst.: %lds %ldus\n",(long)usage.ru_utime.tv_sec,(long)usage.ru_utime.tv_usec); - pf("\tTime executing system inst.: %lds %ldus\n",(long)usage.ru_stime.tv_sec,(long)usage.ru_stime.tv_usec); - pf("\tMax. Phy. memory usage: %ldkB\n",(long)usage.ru_maxrss); - pf("\tPage fault number (no io): %ld\n",(long)usage.ru_minflt); - pf("\tPage fault number (requiring io): %ld\n",(long)usage.ru_majflt); - pf("\tNumber of file system read: %ld\n",(long)usage.ru_inblock); - pf("\tNumber of filesystem write: %ld\n",(long)usage.ru_oublock); - pf("\tNumber of context switch (process origin, io...): %ld\n",(long)usage.ru_nvcsw); - pf("\tNumber of context switch (os origin, priority...): %ld\n",(long)usage.ru_nivcsw); - } + int st = getrusage(RUSAGE_SELF,&usage); + if (!st) { + pf("\nRun time: %lluh %llus\n",(unsigned long long)elapse/3600,(unsigned long long)(elapse - (elapse/3600))); + pf("\tTime executing user inst.: %lds %ldus\n",(long)usage.ru_utime.tv_sec,(long)usage.ru_utime.tv_usec); + pf("\tTime executing system inst.: %lds %ldus\n",(long)usage.ru_stime.tv_sec,(long)usage.ru_stime.tv_usec); + pf("\tMax. Phy. memory usage: %ldkB\n",(long)usage.ru_maxrss); + pf("\tPage fault number (no io): %ld\n",(long)usage.ru_minflt); + pf("\tPage fault number (requiring io): %ld\n",(long)usage.ru_majflt); + pf("\tNumber of file system read: %ld\n",(long)usage.ru_inblock); + pf("\tNumber of filesystem write: %ld\n",(long)usage.ru_oublock); + pf("\tNumber of context switch (process origin, io...): %ld\n",(long)usage.ru_nvcsw); + pf("\tNumber of context switch (os origin, priority...): %ld\n",(long)usage.ru_nivcsw); + } } void signal_handler(int sig) { @@ -180,9 +180,9 @@ void signal_handler(int sig) { backtrace_symbols_fd(array, size, 2); exit(-1); } else { - if(sig==SIGINT ||sig==SOFTMODEM_RTSIGNAL) - softmodem_printresources(sig,(telnet_printfunc_t)printf); - if (sig != SOFTMODEM_RTSIGNAL) { + if(sig==SIGINT ||sig==SOFTMODEM_RTSIGNAL) + softmodem_printresources(sig,(telnet_printfunc_t)printf); + if (sig != SOFTMODEM_RTSIGNAL) { printf("Linux signal %s...\n",strsignal(sig)); exit_function(__FILE__, __FUNCTION__, __LINE__,"softmodem starting exit procedure\n"); } @@ -192,7 +192,7 @@ void signal_handler(int sig) { void set_softmodem_sighandler(void) { - struct sigaction act,oldact; + struct sigaction act,oldact; clock_gettime(CLOCK_BOOTTIME, &start); memset(&act,0,sizeof(act)); act.sa_handler=signal_handler; @@ -201,6 +201,6 @@ void set_softmodem_sighandler(void) { signal(SIGSEGV, signal_handler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); - signal(SIGABRT, signal_handler); + signal(SIGABRT, signal_handler); } diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 7684dad948..449d2e0957 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -38,6 +38,11 @@ extern "C" #endif /* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ #define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" +#define CONFIG_HLP_SPLIT73 "Split 7.3 (below rate matching) option: ::" +#define CONFIG_HLP_TPOOL "Thread pool configuration: \n\ + default no pool (runs in calling thread),\n\ + list of cores, comma separated (negative value is no core affinity)\n\ + example: -1,3 launches two working threads one floating, the second set on core 3" #define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n" #define CONFIG_HLP_CALUER "set UE RX calibration\n" #define CONFIG_HLP_CALUERM "" @@ -54,6 +59,7 @@ extern "C" #define CONFIG_HLP_EXTS "tells hardware to use an external timing reference\n" #define CONFIG_HLP_DMRSSYNC "tells RU to insert DMRS in subframe 1 slot 0" #define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n" +#define CONFIG_HLP_TME "tells hardware to use a time reference (0:internal, 1:external, 2:gpsdo)\n" #define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n" #define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" #define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" @@ -89,6 +95,8 @@ extern "C" /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-----------------------------------------------------------------------------------------------------------------------------------------------------*/ #define RF_CONFIG_FILE softmodem_params.rf_config_file +#define SPLIT73 softmodem_params.split73 +#define TP_CONFIG softmodem_params.threadPoolConfig #define PHY_TEST softmodem_params.phy_test #define DO_RA softmodem_params.do_ra #define WAIT_FOR_SYNC softmodem_params.wait_for_sync @@ -105,10 +113,13 @@ extern "C" #define CMDLINE_PARAMS_DESC { \ {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\ + {"split73", CONFIG_HLP_SPLIT73, 0, strptr:(char **)&SPLIT73, defstrval:NULL, TYPE_STRING, sizeof(SPLIT73)},\ + {"thread-pool", CONFIG_HLP_TPOOL, 0, strptr:(char **)&TP_CONFIG, defstrval:"n", TYPE_STRING, sizeof(TP_CONFIG)}, \ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \ {"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, iptr:&DO_RA, defintval:0, TYPE_INT, 0}, \ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \ - {"clock", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ + {"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ + {"time-source", CONFIG_HLP_TME, 0, uptr:&TIMING_SOURCE, defintval:0, TYPE_UINT, 0}, \ {"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&WAIT_FOR_SYNC, defintval:0, TYPE_INT, 0}, \ {"single-thread-enable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&SINGLE_THREAD_FLAG, defintval:0, TYPE_INT, 0}, \ {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0, TYPE_UINT64, 0}, \ @@ -194,6 +205,8 @@ typedef struct { uint64_t optmask; //THREAD_STRUCT thread_struct; char rf_config_file[1024]; + char split73[1024]; + char threadPoolConfig[1024]; int phy_test; int do_ra; uint8_t usim_test; diff --git a/executables/split_headers.h b/executables/split_headers.h new file mode 100644 index 0000000000..4e328f74c4 --- /dev/null +++ b/executables/split_headers.h @@ -0,0 +1,329 @@ +/* +* 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 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* 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 __SPLIT_HEADERS_H +#define __SPLIT_HEADERS_H + +#include +#include +#include + +#define CU_PORT "7878" +#define DU_PORT "8787" +#define SPLIT73_CU 1 +#define SPLIT73_DU 2 +extern int split73; + +#define MTU 65536 +#define UDP_TIMEOUT 900000L // in micro second (struct timeval, NOT struct timespec) +// linux may timeout for a much longer time (up to 10ms) +#define blockAlign 32 //bytes to align memory for SIMD copy (256 bits vectors) + +// FS6 transport configuration and handler +typedef struct { + char *sourceIP; + char *sourcePort; + char *destIP; + char *destPort; + struct addrinfo *destAddr; + int sockHandler; +} UDPsock_t; + +#define CTsentCUv0 0xA500 +#define CTsentDUv0 0x5A00 + +// Main FS6 transport layer header +// All packets starts with this header +typedef struct commonUDP_s { + uint64_t timestamp; // id of the group (subframe for LTE) + uint16_t nbBlocks; // total number of blocks for this timestamp + uint16_t blockID; // id: 0..nbBocks-1 + uint16_t contentType; // defines the content format + uint16_t contentBytes; // will be sent in a UDP packet, so must be < 2^16 bytes + uint64_t senderClock; +} commonUDP_t; + +// FS6 UL common header (DU to CU) +// gives the RACH detection data and is always sent to inform the CU that a subframe arrived +typedef struct { + uint16_t max_preamble[4]; + uint16_t max_preamble_energy[4]; + uint16_t max_preamble_delay[4]; + uint16_t avg_preamble_energy[4]; +} fs6_ul_t; + +// FS6 DL common header (CU to DU) +// gives the DCI configuration from each subframe +typedef struct { + uint8_t pbch_pdu[4]; + int num_pdcch_symbols; + int num_dci; + DCI_ALLOC_t dci_alloc[8]; + int num_mdci; + int amp; + LTE_eNB_PHICH phich_vars; + uint64_t DuClock; + uint64_t CuSpentMicroSec; +} fs6_dl_t; + +// a value to type all sub packets, +// to detect errors, and to be able to extend to other versions +// the first byte of each sub structure should match one of these values +enum pckType { + fs6UlConfig=25, + fs6DlConfig=26, + fs6ULConfigCCH=27, + fs6ULsch=28, + fs6ULcch=29, + fs6ULindicationHarq=40, + fs6ULindicationSr=41, +}; + +// CU to DU definition of a future UL subframe decode +// defines a UE future data plane +typedef struct { + enum pckType type:8; + uint16_t UE_id; + int8_t harq_pid; + UE_type_t ue_type; + + uint8_t dci_alloc; + uint8_t rar_alloc; + SCH_status_t status; + uint8_t Msg3_flag; + uint8_t subframe; + uint32_t frame; + uint8_t handled; + uint8_t phich_active; + uint8_t phich_ACK; + uint16_t previous_first_rb; + uint32_t B; + uint32_t G; + UCI_format_t uci_format; + uint8_t Or2; + uint8_t o_RI[2]; + uint8_t o_ACK[4]; + uint8_t O_ACK; + uint8_t o_RCC; + int16_t q_ACK[MAX_ACK_PAYLOAD]; + int16_t q_RI[MAX_RI_PAYLOAD]; + uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS]; + uint8_t ndi; + uint8_t round; + uint8_t rvidx; + uint8_t Nl; + uint8_t n_DMRS; + uint8_t previous_n_DMRS; + uint8_t n_DMRS2; + int32_t delta_TF; + uint32_t repetition_number ; + uint32_t total_number_of_repetitions; + + uint16_t harq_mask; + uint16_t nb_rb; + uint8_t Qm; + uint16_t first_rb; + uint8_t O_RI; + uint8_t Or1; + uint16_t Msc_initial; + uint8_t Nsymb_initial; + uint8_t V_UL_DAI; + uint8_t srs_active; + uint32_t TBS; + uint8_t Nsymb_pusch; + uint8_t Mlimit; + uint8_t max_turbo_iterations; + uint8_t bundling; + uint16_t beta_offset_cqi_times8; + uint16_t beta_offset_ri_times8; + uint16_t beta_offset_harqack_times8; + uint8_t Msg3_active; + uint16_t rnti; + uint8_t cyclicShift; + uint8_t cooperation_flag; + uint8_t num_active_cba_groups; + uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP]; +} fs6_dl_ulsched_t; + +// CU to DU defintion of a DL packet for a given UE +// The data itself is padded at the end of this structure +typedef struct { + enum pckType type:8; + int UE_id; + int8_t harq_pid; + uint16_t rnti; + int16_t sqrt_rho_a; + int16_t sqrt_rho_b; + CEmode_t CEmode:8; + uint16_t nb_rb; + uint8_t Qm; + int8_t Nl; + uint8_t pdsch_start; + uint8_t sib1_br_flag; + uint16_t i0; + uint32_t rb_alloc[4]; + int dataLen; +} fs6_dl_uespec_t; + +// CU to DU definition of CCH channel +typedef struct { + int16_t UE_id; + LTE_eNB_UCI cch_vars; +} fs6_dl_uespec_ulcch_element_t; + +// header to group all UE CCH channels definitions in one UDP packet +typedef struct { + enum pckType type:8; + int16_t nb_active_ue; +} fs6_dl_uespec_ulcch_t; + +// code internal, not transmitted as this +typedef struct { + int ta; +} ul_propagation_t; + +// One UE UL data, data plane, UE data appended after the header +typedef struct { + enum pckType type:8; + short UE_id; + uint8_t harq_id; + uint8_t segment; + int segLen; + int r_offset; + int G; + int ulsch_power[2]; + uint8_t o_ACK[4]; + uint8_t O_ACK; + int ta; + uint8_t o[MAX_CQI_BYTES]; + uint8_t cqi_crc_status; +} fs6_ul_uespec_t; + +// UL UCI (control plane), per UE +typedef struct { + enum pckType type:8; + int UEid; + int frame; + int subframe; + LTE_eNB_UCI uci; + uint8_t harq_ack[4]; + uint8_t tdd_mapping_mode; + uint16_t tdd_multiplexing_mask; + unsigned short n0_subband_power_dB; + uint16_t rnti; + int32_t stat; +} fs6_ul_uespec_uci_element_t; + +// all segments UCI grouped in one UDP packet +typedef struct { + enum pckType type:8; + int16_t nb_active_ue; +} fs6_ul_uespec_uci_t; + + +bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); +int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType); +int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType); + +#define initBufferZone(xBuf) \ + uint8_t xBuf[FS6_BUF_SIZE]; \ + ((commonUDP_t *)xBuf)->nbBlocks=0; + +#define hUDP(xBuf) ((commonUDP_t *)xBuf) +#define hDL(xBuf) ((fs6_dl_t*)(((commonUDP_t *)xBuf)+1)) +#define hUL(xBuf) ((fs6_ul_t*)(((commonUDP_t *)xBuf)+1)) +#define hDLUE(xBuf) ((fs6_dl_uespec_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hTxULUE(xBuf) ((fs6_dl_ulsched_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hTxULcch(xBuf) ((fs6_dl_uespec_ulcch_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hULUE(xBuf) ((fs6_ul_uespec_t*) (((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hULUEuci(xBuf) ((fs6_ul_uespec_uci_t*) (((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))+1)) + +static inline size_t alignedSize(uint8_t *ptr) { + commonUDP_t *header=(commonUDP_t *) ptr; + return ((header->contentBytes+sizeof(commonUDP_t)+blockAlign-1)/blockAlign)*blockAlign; +} + +static inline void *commonUDPdata(uint8_t *ptr) { + return (void *) (((commonUDP_t *)ptr)+1); +} + +void setAllfromTS(uint64_t TS, L1_rxtx_proc_t *proc); +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, + uint16_t rnti, int32_t stat); +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset); +void *cu_fs6(void *arg); +void *du_fs6(void *arg); +void fill_rf_config(RU_t *ru, char *rf_config_file); +int init_rf(RU_t *ru); +void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc); +void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); +void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe); +void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); +bool dlsch_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int harq_pid, + LTE_eNB_DLSCH_t *dlsch, + LTE_eNB_UE_stats *ue_stats) ; +void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req); +void pdsch_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int harq_pid, + LTE_eNB_DLSCH_t *dlsch, + LTE_eNB_DLSCH_t *dlsch1); +void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); +void uci_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc); +void ocp_rx_prach(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + RU_t *ru, + uint16_t *max_preamble, + uint16_t *max_preamble_energy, + uint16_t *max_preamble_delay, + uint16_t *avg_preamble_energy, + uint16_t Nf, + uint8_t tdd_mapindex, + uint8_t br_flag); +void rx_prach0(PHY_VARS_eNB *eNB, + RU_t *ru, + int frame_prach, + int subframe, + uint16_t *max_preamble, + uint16_t *max_preamble_energy, + uint16_t *max_preamble_delay, + uint16_t *avg_preamble_energy, + uint16_t Nf, + uint8_t tdd_mapindex, + uint8_t br_flag, + uint8_t ce_level + ); +void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); + +// mistakes in main OAI +void phy_init_RU(RU_t *); +void fep_full(RU_t *ru, int subframe); +void feptx_prec(RU_t *ru,int frame,int subframe); +void feptx_ofdm(RU_t *ru, int frame, int subframe); +void oai_subframe_ind(uint16_t sfn, uint16_t sf); +extern uint16_t sf_ahead; +#endif diff --git a/executables/transport_split.c b/executables/transport_split.c new file mode 100644 index 0000000000..f380eb90e3 --- /dev/null +++ b/executables/transport_split.c @@ -0,0 +1,195 @@ +/* +* 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 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org +*/ + + + +#include +#include /* See NOTES */ +#include +#include +#include +#include +#include + +bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result) { + struct addrinfo hints= {0}, *servinfo, *p; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; + int status; + + if ((status = getaddrinfo(sourceIP, sourcePort, &hints, &servinfo)) != 0) { + LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status)); + return false; + } + + // loop through all the results and bind to the first we can + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((result->sockHandler = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + LOG_W(GTPU,"socket: %s\n", strerror(errno)); + continue; + } + + if (bind(result->sockHandler, p->ai_addr, p->ai_addrlen) == -1) { + close(result->sockHandler); + LOG_W(GTPU,"bind: %s\n", strerror(errno)); + continue; + } + + break; // if we get here, we must have connected successfully + } + + if (p == NULL) { + // looped off the end of the list with no successful bind + LOG_E(GTPU,"failed to bind socket: %s %s \n",sourceIP,sourcePort); + return false; + } + + freeaddrinfo(servinfo); // all done with this structure + + if ((status = getaddrinfo(destIP, destPort, &hints, &servinfo)) != 0) { + LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status)); + return false; + } + + if (servinfo) { + result->destAddr=servinfo; + } else { + LOG_E(PHY,"No valid UDP addr: %s:%s\n",destIP, destPort); + return false; + } + + int enable=1; + AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); + struct timeval tv= {0,UDP_TIMEOUT}; + + if (IS_SOFTMODEM_RFSIM) + tv.tv_sec=2; //debug: wait 2 seconds for human understanding + + AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); + // Make a send/recv buffer larger than a a couple of subframe + // so the kernel will store for us in and out paquets + int buff=1000*1000*10; + AssertFatal ( setsockopt(result->sockHandler, SOL_SOCKET, SO_SNDBUF, &buff, sizeof(buff)) == 0, ""); + AssertFatal ( setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVBUF, &buff, sizeof(buff)) == 0, ""); + return true; +} + +// sock: udp socket +// bufferZone: a reception area of bufferSize +int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType) { + int rcved=0; + commonUDP_t *bufOrigin=(commonUDP_t *)bufferZone; + static uint8_t crossData[65536]; + static int crossDataSize=0; + + if (crossDataSize) { + LOG_D(HW,"copy a block received in previous subframe\n"); + memcpy(bufferZone, crossData, crossDataSize); + rcved=1; + bufferZone+=crossDataSize; + crossDataSize=0; + } + + do { + //read all subframe data from the control unit + int ret=recv(sock->sockHandler, bufferZone, bufferSize, 0); + + if ( ret==-1) { + if ( errno == EWOULDBLOCK || errno== EINTR ) { + LOG_I(HW,"Received: Timeout, subframe incomplete\n"); + return rcved; + } else { + LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno)); + return -1; + } + } else { + if (hUDP(bufferZone)->contentType != contentType) + abort(); + + if (rcved && bufOrigin->timestamp != hUDP(bufferZone)->timestamp ) { + if ( hUDP(bufferZone)->timestamp > bufOrigin->timestamp ) { + LOG_W(HW,"Received data for TS: %lu before end of TS : %lu completion\n", + hUDP(bufferZone)->timestamp, + bufOrigin->timestamp); + memcpy(crossData, bufferZone, ret ); + crossDataSize=ret; + return rcved; + } else { + LOG_W(HW,"Dropping late packet\n"); + continue; + } + } + + rcved++; + bufferZone+=ret; + } + + LOG_D(HW,"Received: blocks: %d/%d, size %d, TS: %lu\n", + rcved, bufOrigin->nbBlocks, ret, bufOrigin->timestamp); + } while ( rcved == 0 || rcved < bufOrigin->nbBlocks ); + + return rcved; +} + +int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType) { + commonUDP_t *UDPheader=(commonUDP_t *)bufferZone ; + UDPheader->contentType=contentType; + UDPheader->senderClock=rdtsc(); + int nbBlocks=UDPheader->nbBlocks; + int blockId=0; + + if (nbBlocks <= 0 ) { + LOG_E(PHY,"FS6: can't send blocks: %d\n", nbBlocks); + return 0; + } + + do { + if (blockId > 0 ) { + commonUDP_t *currentHeader=(commonUDP_t *)bufferZone; + currentHeader->timestamp=UDPheader->timestamp; + currentHeader->nbBlocks=UDPheader->nbBlocks; + currentHeader->blockID=blockId; + currentHeader->contentType=UDPheader->contentType; + memcpy(commonUDPdata((void *)currentHeader), commonUDPdata(bufferZone), secondHeaderSize); + } + + blockId++; + int sz=alignedSize(bufferZone); + // Let's use the first address returned by getaddrinfo() + int ret=sendto(sock->sockHandler, bufferZone, sz, 0, + sock->destAddr->ai_addr, sock->destAddr->ai_addrlen); + + if ( ret != sz ) + LOG_W(HW,"Wrote socket doesn't return size %d (val: %d, errno:%d, %s)\n", + sz, ret, errno, strerror(errno)); + + LOG_D(HW,"Sent: TS: %lu, blocks %d/%d, block size : %d \n", + UDPheader->timestamp, UDPheader->nbBlocks-nbBlocks, UDPheader->nbBlocks, sz); + bufferZone+=sz; + nbBlocks--; + } while (nbBlocks); + + return 0; +} diff --git a/nfapi/oai_integration/nfapi.c b/nfapi/oai_integration/nfapi.c index 4fc35fd951..86d1ae3127 100644 --- a/nfapi/oai_integration/nfapi.c +++ b/nfapi/oai_integration/nfapi.c @@ -29,7 +29,7 @@ typedef struct { nfapi_mode_t nfapi_mode; } nfapi_params_t; -static nfapi_params_t nfapi_params; +static nfapi_params_t nfapi_params = {0}; void set_thread_priority(int priority) { //printf("%s(priority:%d)\n", __FUNCTION__, priority); diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index f07fb1ad23..59857659c1 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -49,7 +49,6 @@ extern RAN_CONTEXT_t RC; #include "fapi_stub.h" //#include "fapi_l1.h" #include "common/utils/LOG/log.h" -#include "openair2/LAYER2/MAC/mac_proto.h" #include "PHY/INIT/phy_init.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" @@ -692,13 +691,14 @@ void pnf_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header) { free(header); } -int pnf_phy_hi_dci0_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) { +int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) { if (req->hi_dci0_request_body.number_of_dci == 0 && req->hi_dci0_request_body.number_of_hi == 0) LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi); //phy_info* phy = (phy_info*)(pnf_p7->user_data); struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; - L1_rxtx_proc_t *proc = &eNB->proc.L1_proc; + if (proc ==NULL) + proc = &eNB->proc.L1_proc; for (int i=0; ihi_dci0_request_body.number_of_dci + req->hi_dci0_request_body.number_of_hi; i++) { //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); @@ -719,7 +719,7 @@ int pnf_phy_hi_dci0_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t * return 0; } -int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { +int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { if (RC.ru == 0) { return -1; } @@ -740,7 +740,8 @@ int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request int sfn = NFAPI_SFNSF2SFN(req->sfn_sf); int sf = NFAPI_SFNSF2SF(req->sfn_sf); struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; - L1_rxtx_proc_t *proc = &eNB->proc.L1_proc; + if (proc==NULL) + proc = &eNB->proc.L1_proc; nfapi_dl_config_request_pdu_t *dl_config_pdu_list = req->dl_config_request_body.dl_config_pdu_list; LTE_eNB_PDCCH *pdcch_vars = &eNB->pdcch_vars[sf&1]; pdcch_vars->num_pdcch_symbols = req->dl_config_request_body.number_pdcch_ofdm_symbols; @@ -797,7 +798,7 @@ int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request uint8_t *dlsch_sdu = tx_pdus[UE_id][harq_pid]; memcpy(dlsch_sdu, tx_pdu->segments[0].segment_data, tx_pdu->segments[0].segment_length); //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() DLSCH:pdu_index:%d handle_nfapi_dlsch_pdu(eNB, proc_rxtx, dlsch_pdu, transport_blocks:%d sdu:%p) eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols:%d\n", __FUNCTION__, rel8_pdu->pdu_index, rel8_pdu->transport_blocks, dlsch_sdu, eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols); - handle_nfapi_dlsch_pdu( eNB, sfn,sf, &eNB->proc.L1_proc, &dl_config_pdu_list[i], rel8_pdu->transport_blocks-1, dlsch_sdu); + handle_nfapi_dlsch_pdu( eNB, sfn,sf, proc, &dl_config_pdu_list[i], rel8_pdu->transport_blocks-1, dlsch_sdu); } else { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), rel8_pdu->pdu_index); } @@ -837,7 +838,7 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { return 0; } -int pnf_phy_ul_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { +int pnf_phy_ul_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), @@ -866,7 +867,8 @@ int pnf_phy_ul_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request uint16_t curr_sfn = NFAPI_SFNSF2SFN(req->sfn_sf); uint16_t curr_sf = NFAPI_SFNSF2SF(req->sfn_sf); struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; - L1_rxtx_proc_t *proc = &eNB->proc.L1_proc; + if (proc==NULL) + proc = &eNB->proc.L1_proc; nfapi_ul_config_request_pdu_t *ul_config_pdu_list = req->ul_config_request_body.ul_config_pdu_list; for (int i=0; iul_config_request_body.number_of_pdus; i++) { diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index e213d785f1..2c8201737c 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -23,5 +23,5 @@ #define NFAPI_PNF_H__ int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); - +void oai_subframe_ind(uint16_t sfn, uint16_t sf); #endif diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index 5fe1c53a54..650bda4f78 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -10,6 +10,7 @@ #define _NFAPI_NR_INTERFACE_H_ #include "nfapi_interface.h" +#include #define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5 #define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64 diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 8d17416a41..d169177d6b 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -24,6 +24,7 @@ extern "C" { #include "nfapi_interface.h" #include "debug.h" +#include #include @@ -619,21 +620,21 @@ typedef struct nfapi_pnf_p7_config * \param req A pointer to the dl config request message structure * \return not currently used */ - int (*dl_config_req)(nfapi_pnf_p7_config_t* config, nfapi_dl_config_request_t* req); + int (*dl_config_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_dl_config_request_t* req); /*! A callback for the UL_CONFIG.request * \param config A poiner to the PNF P7 config * \param req A pointer to the ul config request message structure * \return not currently used */ - int (*ul_config_req)(nfapi_pnf_p7_config_t* config, nfapi_ul_config_request_t* req); + int (*ul_config_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_ul_config_request_t* req); /*! A callback for the HI_DCI0.request * \param config A poiner to the PNF P7 config * \param req A pointer to the hi dci0 request message structure * \return not currently used */ - int (*hi_dci0_req)(nfapi_pnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); + int (*hi_dci0_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); /*! A callback for the TX_REQ.request * \param config A poiner to the PNF P7 config diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c index 7310fc0c66..dda0d0fdc6 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c @@ -39,7 +39,7 @@ nfapi_pnf_config_t* nfapi_pnf_config_create() _this->_public.codec_config.allocate = &malloc; _this->_public.codec_config.deallocate = &free; - return &(_this->_public); + return (nfapi_pnf_config_t* )_this; } void nfapi_pnf_config_destory(nfapi_pnf_config_t* config) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 9446730375..5ba912e059 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -576,20 +576,20 @@ void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) { pnf_p7->_public.dummy_subframe.dl_config_req->sfn_sf = sfn_sf; //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - enter\n"); - (pnf_p7->_public.dl_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req); + (pnf_p7->_public.dl_config_req)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req); //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - exit\n"); } if(pnf_p7->_public.ul_config_req && pnf_p7->_public.dummy_subframe.ul_config_req) { pnf_p7->_public.dummy_subframe.ul_config_req->sfn_sf = sfn_sf; NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy ul_config_req - enter\n"); - (pnf_p7->_public.ul_config_req)(&pnf_p7->_public, pnf_p7->_public.dummy_subframe.ul_config_req); + (pnf_p7->_public.ul_config_req)(NULL, &pnf_p7->_public, pnf_p7->_public.dummy_subframe.ul_config_req); } if(pnf_p7->_public.hi_dci0_req && pnf_p7->_public.dummy_subframe.hi_dci0_req) { pnf_p7->_public.dummy_subframe.hi_dci0_req->sfn_sf = sfn_sf; NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy hi_dci0 - enter\n"); - (pnf_p7->_public.hi_dci0_req)(&pnf_p7->_public, pnf_p7->_public.dummy_subframe.hi_dci0_req); + (pnf_p7->_public.hi_dci0_req)(NULL, &pnf_p7->_public, pnf_p7->_public.dummy_subframe.hi_dci0_req); } if(pnf_p7->_public.lbt_dl_config_req && pnf_p7->_public.dummy_subframe.lbt_dl_config_req) { @@ -699,7 +699,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(tx_subframe_buffer->dl_config_req != 0) { if(pnf_p7->_public.dl_config_req) - (pnf_p7->_public.dl_config_req)(&(pnf_p7->_public), tx_subframe_buffer->dl_config_req); + (pnf_p7->_public.dl_config_req)(NULL, &(pnf_p7->_public), tx_subframe_buffer->dl_config_req); //deallocate_nfapi_dl_config_request(subframe_buffer->dl_config_req, pnf_p7); } @@ -709,14 +709,14 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(pnf_p7->_public.dl_config_req && pnf_p7->_public.dummy_subframe.dl_config_req) { pnf_p7->_public.dummy_subframe.dl_config_req->sfn_sf = sfn_sf_tx; - (pnf_p7->_public.dl_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req); + (pnf_p7->_public.dl_config_req)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req); } } if(tx_subframe_buffer->hi_dci0_req != 0) { if(pnf_p7->_public.hi_dci0_req) - (pnf_p7->_public.hi_dci0_req)(&(pnf_p7->_public), tx_subframe_buffer->hi_dci0_req); + (pnf_p7->_public.hi_dci0_req)(NULL, &(pnf_p7->_public), tx_subframe_buffer->hi_dci0_req); //deallocate_nfapi_hi_dci0_request(subframe_buffer->hi_dci0_req, pnf_p7); } @@ -726,7 +726,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(pnf_p7->_public.hi_dci0_req && pnf_p7->_public.dummy_subframe.hi_dci0_req) { pnf_p7->_public.dummy_subframe.hi_dci0_req->sfn_sf = sfn_sf_tx; - (pnf_p7->_public.hi_dci0_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.hi_dci0_req); + (pnf_p7->_public.hi_dci0_req)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_subframe.hi_dci0_req); } } @@ -777,7 +777,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(subframe_buffer->ul_config_req != 0) { if(pnf_p7->_public.ul_config_req) - (pnf_p7->_public.ul_config_req)(&(pnf_p7->_public), subframe_buffer->ul_config_req); + (pnf_p7->_public.ul_config_req)(NULL, &(pnf_p7->_public), subframe_buffer->ul_config_req); //deallocate_nfapi_ul_config_request(subframe_buffer->ul_config_req, pnf_p7); } @@ -787,7 +787,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(pnf_p7->_public.ul_config_req && pnf_p7->_public.dummy_subframe.ul_config_req) { pnf_p7->_public.dummy_subframe.ul_config_req->sfn_sf = sfn_sf; - (pnf_p7->_public.ul_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.ul_config_req); + (pnf_p7->_public.ul_config_req)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_subframe.ul_config_req); } } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 0aba0a29f5..59d7f3eb4f 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -55,7 +55,7 @@ nfapi_vnf_config_t* nfapi_vnf_config_create() _this->_public.codec_config.deallocate = &free; - return &(_this->_public); + return (nfapi_vnf_config_t* )_this; } void nfapi_vnf_config_destory(nfapi_vnf_config_t* config) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 35bd5e4c1b..a0efeeb5f4 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -47,7 +47,7 @@ nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create() _this->_public.codec_config.deallocate = &free; - return &(_this->_public); + return (nfapi_vnf_p7_config_t*)_this; } void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config) diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 552af99c41..ce6f9996de 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -529,7 +529,7 @@ int main(int argc, char *argv[]) time_stats_t time_optim[10], time_decoder[10]; n_iter_stats_t dec_iter[3]; - short BG=0,Zc,Kb; + short BG=0,Zc,Kb=0; while ((c = getopt (argc, argv, "q:r:s:S:l:n:d:i:t:u:h")) != -1) switch (c) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h index 10b45ac0e7..b76750459d 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h @@ -135,25 +135,25 @@ static inline void nrLDPC_llr2llrProcBuf(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrL */ static inline void nrLDPC_llr2CnProcBuf_BG1(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrLDPC_procBuf* p_procBuf, uint16_t Z) { - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; - const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; - const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; - const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; + const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; + const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; - const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->posBnInCnProcBuf[0]; - const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->posBnInCnProcBuf[1]; - const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->posBnInCnProcBuf[2]; - const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->posBnInCnProcBuf[3]; - const uint8_t (*lut_posBnInCnProcBuf_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->posBnInCnProcBuf[4]; - const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->posBnInCnProcBuf[5]; - const uint8_t (*lut_posBnInCnProcBuf_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->posBnInCnProcBuf[6]; - const uint8_t (*lut_posBnInCnProcBuf_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->posBnInCnProcBuf[7]; - const uint8_t (*lut_posBnInCnProcBuf_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->posBnInCnProcBuf[8]; + const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->posBnInCnProcBuf[0]; + const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->posBnInCnProcBuf[1]; + const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->posBnInCnProcBuf[2]; + const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->posBnInCnProcBuf[3]; + const uint8_t (*lut_posBnInCnProcBuf_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->posBnInCnProcBuf[4]; + const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->posBnInCnProcBuf[5]; + const uint8_t (*lut_posBnInCnProcBuf_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->posBnInCnProcBuf[6]; + const uint8_t (*lut_posBnInCnProcBuf_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->posBnInCnProcBuf[7]; + const uint8_t (*lut_posBnInCnProcBuf_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->posBnInCnProcBuf[8]; const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; @@ -344,19 +344,19 @@ static inline void nrLDPC_llr2CnProcBuf_BG1(t_nrLDPC_lut* p_lut, int8_t* llr, t_ */ static inline void nrLDPC_llr2CnProcBuf_BG2(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrLDPC_procBuf* p_procBuf, uint16_t Z) { - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; - const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->posBnInCnProcBuf[0]; - const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->posBnInCnProcBuf[1]; - const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->posBnInCnProcBuf[2]; - const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->posBnInCnProcBuf[3]; - const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->posBnInCnProcBuf[4]; - const uint8_t (*lut_posBnInCnProcBuf_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->posBnInCnProcBuf[5]; + const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->posBnInCnProcBuf[0]; + const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->posBnInCnProcBuf[1]; + const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->posBnInCnProcBuf[2]; + const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->posBnInCnProcBuf[3]; + const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->posBnInCnProcBuf[4]; + const uint8_t (*lut_posBnInCnProcBuf_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->posBnInCnProcBuf[5]; const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; @@ -483,26 +483,26 @@ static inline void nrLDPC_cn2bnProcBuf_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; - const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; - const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; - const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; - const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; - const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; - const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (const uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (const uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; - const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; - const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; - const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; - const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; - const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; - const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (const uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (const uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; int8_t* bnProcBuf = p_procBuf->bnProcBuf; @@ -626,34 +626,34 @@ static inline void nrLDPC_cn2bnProcBuf_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; - const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; - const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; - const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; + const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; + const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; - const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; - const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; - const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; - const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; - const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; - const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; - const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; - const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; - const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (const uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (const uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (const uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (const uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; + const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (const uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; - const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; - const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; - const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; - const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; - const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; - const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; - const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; - const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (const uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (const uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (const uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (const uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; + const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (const uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; int8_t* bnProcBuf = p_procBuf->bnProcBuf; @@ -824,26 +824,26 @@ static inline void nrLDPC_bn2cnProcBuf_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; - const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; - const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; - const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; - const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; - const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; - const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (const uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (const uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; - const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; - const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; - const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; - const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; - const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; - const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (const uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (const uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; int8_t* cnProcBuf = p_procBuf->cnProcBuf; int8_t* bnProcBufRes = p_procBuf->bnProcBufRes; @@ -966,34 +966,34 @@ static inline void nrLDPC_bn2cnProcBuf_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; - const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; - const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; - const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; + const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; + const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; - const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; - const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; - const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; - const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; - const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; - const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; - const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; - const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; - const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (const uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (const uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (const uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (const uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; + const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (const uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; - const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; - const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; - const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; - const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; - const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; - const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; - const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; - const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (const uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (const uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (const uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (const uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; + const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (const uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; int8_t* cnProcBuf = p_procBuf->cnProcBuf; int8_t* bnProcBufRes = p_procBuf->bnProcBufRes; diff --git a/openair1/PHY/INIT/lte_init_ru.c b/openair1/PHY/INIT/lte_init_ru.c index 207bf249f5..dddd6b1bd5 100644 --- a/openair1/PHY/INIT/lte_init_ru.c +++ b/openair1/PHY/INIT/lte_init_ru.c @@ -38,7 +38,7 @@ int phy_init_RU(RU_t *ru) { LTE_DL_FRAME_PARMS *fp = ru->frame_parms; RU_CALIBRATION *calibration = &ru->calibration; int i,j,p,re; - init_dfts(); + //load_dftslib(); LOG_I(PHY,"Initializing RU signal buffers (if_south %s) nb_tx %d\n",ru_if_types[ru->if_south],ru->nb_tx); if (ru->is_slave == 1) { @@ -76,7 +76,7 @@ int phy_init_RU(RU_t *ru) { } if (ru->function != NGFI_RRU_IF5) { // we need to do RX/TX RU processing - init_dfts(); + load_dftslib(); init_7_5KHz(); LOG_I(PHY,"nb_tx %d\n",ru->nb_tx); ru->common.rxdata_7_5kHz = (int32_t **)malloc16(ru->nb_rx*sizeof(int32_t *) ); diff --git a/openair1/PHY/INIT/lte_init_ue.c b/openair1/PHY/INIT/lte_init_ue.c index 1a6f0081e1..082db61da9 100644 --- a/openair1/PHY/INIT/lte_init_ue.c +++ b/openair1/PHY/INIT/lte_init_ue.c @@ -625,7 +625,7 @@ int init_lte_ue_signal(PHY_VARS_UE *ue, int th_id; LOG_D(PHY,"Initializing UE vars (abstraction %"PRIu8") for eNB TXant %"PRIu8", UE RXant %"PRIu8"\n",abstraction_flag,fp->nb_antennas_tx,fp->nb_antennas_rx); crcTableInit(); - init_dfts(); + load_dftslib(); init_frame_parms(&ue->frame_parms,1); lte_sync_time_init(&ue->frame_parms); init_lte_top(&ue->frame_parms); diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index ee64c5a32a..6a022b4fb1 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -97,7 +97,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, while(gNB->configured == 0) usleep(10000); - init_dfts(); + load_dftslib(); /* LOG_I(PHY,"[gNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d nb_antennas_tx:%u nb_antennas_rx:%u PRACH[rootSequenceIndex:%u prach_Config_enabled:%u configIndex:%u highSpeed:%u zeroCorrelationZoneConfig:%u freqOffset:%u]\n", gNB->Mod_id, @@ -113,7 +113,8 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, );*/ LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_gNB][MOD %02"PRIu8"][]\n", gNB->Mod_id); crcTableInit(); - init_dfts(); + init_scrambling_luts(); + init_pucch2_luts(); load_nrLDPClib(); // PBCH DMRS gold sequences generation nr_init_pbch_dmrs(gNB); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index b88f9aa0f2..b10ec80205 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -990,7 +990,7 @@ void init_nr_ue_transport(PHY_VARS_NR_UE *ue, void phy_init_nr_top(PHY_VARS_NR_UE *ue) { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; crcTableInit(); - init_dfts(); + load_dftslib(); init_context_synchro_nr(frame_parms); generate_ul_reference_signal_sequences(SHRT_MAX); // Polar encoder init for PBCH diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c index 04fe19ecbc..aaa138fcd9 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c @@ -56,22 +56,22 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, // do ifft of channel estimate switch(frame_parms->N_RB_DL) { case 6: - dft128((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_128,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; case 25: - dft512((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_512,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; case 50: - dft1024((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_1024,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; case 100: - dft2048((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_2048,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_ue.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_ue.c index 7414c3a69d..23f261149a 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_ue.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_ue.c @@ -23,7 +23,6 @@ #include "PHY/defs_UE.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/impl_defs_top.h" -#include "openair2/LAYER2/MAC/mac_proto.h" #include "common/utils/LOG/vcd_signal_dumper.h" diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c index 43c0350efb..2331e253d5 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c @@ -43,7 +43,7 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, uint8_t pilot0,pilot1,pilot2,pilot3; short ch[2], *pil, *rxF, *dl_bf_ch, *dl_bf_ch_prev; - short *fl, *fm, *fr, *fl_dc, *fm_dc, *fr_dc, *f1, *f2l, *f2r; + short *fl=NULL, *fm=NULL, *fr=NULL, *fl_dc=NULL, *fm_dc=NULL, *fr_dc=NULL, *f1, *f2l=NULL, *f2r=NULL; unsigned int *rballoc; int **rxdataF; @@ -58,10 +58,10 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) || - ((frame_parms->Ncp == EXTENDED) && (symbol>=6))) - rballoc = dlsch0_harq->rb_alloc_odd; + ((frame_parms->Ncp == EXTENDED) && (symbol>=6))) + rballoc = dlsch0_harq->rb_alloc_odd; else - rballoc = dlsch0_harq->rb_alloc_even; + rballoc = dlsch0_harq->rb_alloc_even; rxdataF = phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[Ns>>1]].rxdataF; @@ -69,56 +69,56 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0; if (phy_vars_ue->high_speed_flag == 0) // use second channel estimate position for temporary storage - ch_offset = frame_parms->ofdm_symbol_size; + ch_offset = frame_parms->ofdm_symbol_size; else - ch_offset = frame_parms->ofdm_symbol_size*symbol; + ch_offset = frame_parms->ofdm_symbol_size*symbol; + - uespec_nushift = frame_parms->Nid_cell%3; subframe = Ns>>1; - - //generate ue specific pilots - lprime = symbol/3-1; - lte_dl_ue_spec_rx(phy_vars_ue,uespec_pilot,Ns,5,lprime,0,dlsch0_harq->nb_rb); - //LOG_M("uespec_pilot_rx.m","uespec_pilot",uespec_pilot,300,1,1); - if (frame_parms->Ncp==0){ - if (symbol==3 || symbol==6 || symbol==9 || symbol==12) - uespec_pilots = 1; - } else{ - if (symbol==4 || symbol==7 || symbol==10) - uespec_pilots = 1; - } - - if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7)) - uespec_poffset = 2; + //generate ue specific pilots + lprime = symbol/3-1; + lte_dl_ue_spec_rx(phy_vars_ue,uespec_pilot,Ns,5,lprime,0,dlsch0_harq->nb_rb); + //LOG_M("uespec_pilot_rx.m","uespec_pilot",uespec_pilot,300,1,1); - if (phy_vars_ue->frame_parms.Ncp == 0) { // normal prefix - pilot0 = 3; - pilot1 = 6; - pilot2 = 9; - pilot3 = 12; - } else { // extended prefix - pilot0 = 4; - pilot1 = 7; - pilot2 = 10; - } + if (frame_parms->Ncp==0){ + if (symbol==3 || symbol==6 || symbol==9 || symbol==12) + uespec_pilots = 1; + } else{ + if (symbol==4 || symbol==7 || symbol==10) + uespec_pilots = 1; + } - //define the filter - pil_offset = (uespec_nushift+uespec_poffset)%3; - // printf("symbol=%d,pil_offset=%d\n",symbol,pil_offset); - switch (pil_offset) { - case 0: - fl = filt16_l0; - fm = filt16_m0; - fr = filt16_r0; - fl_dc = filt16_l0; - fm_dc = filt16_m0; - fr_dc = filt16_r0; - f1 = filt16_1; - f2l = filt16_2l0; - f2r = filt16_2r0; + if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7)) + uespec_poffset = 2; + + if (phy_vars_ue->frame_parms.Ncp == 0) { // normal prefix + pilot0 = 3; + pilot1 = 6; + pilot2 = 9; + pilot3 = 12; + } else { // extended prefix + pilot0 = 4; + pilot1 = 7; + pilot2 = 10; + } + + //define the filter + pil_offset = (uespec_nushift+uespec_poffset)%3; + // printf("symbol=%d,pil_offset=%d\n",symbol,pil_offset); + switch (pil_offset) { + case 0: + fl = filt16_l0; + fm = filt16_m0; + fr = filt16_r0; + fl_dc = filt16_l0; + fm_dc = filt16_m0; + fr_dc = filt16_r0; + f1 = filt16_1; + f2l = filt16_2l0; + f2r = filt16_2r0; break; case 1: diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c index e50af7cdd8..d221348b44 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c @@ -657,35 +657,35 @@ int lte_dl_channel_estimation(PHY_VARS_UE *ue, } } - void (*idft)(int16_t *,int16_t *, int); + idft_size_idx_t idftsizeidx; switch (ue->frame_parms.ofdm_symbol_size) { case 128: - idft = idft128; - break; - - case 256: - idft = idft256; - break; - - case 512: - idft = idft512; - break; - - case 1024: - idft = idft1024; - break; - - case 1536: - idft = idft1536; - break; - - case 2048: - idft = idft2048; - break; - - default: - idft = idft512; + idftsizeidx = IDFT_128; + break; + + case 256: + idftsizeidx = IDFT_256; + break; + + case 512: + idftsizeidx = IDFT_512; + break; + + case 1024: + idftsizeidx = IDFT_1024; + break; + + case 1536: + idftsizeidx = IDFT_1536; + break; + + case 2048: + idftsizeidx = IDFT_2048; + break; + + default: + idftsizeidx = IDFT_512; break; } @@ -695,7 +695,7 @@ int lte_dl_channel_estimation(PHY_VARS_UE *ue, for (p=0; pframe_parms.nb_antenna_ports_eNB; p++) { if (ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset][(p<<1)+aarx]) { //LOG_I(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d \n", Ns, ue->current_thread_id[Ns>>1], l); - idft((int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset][(p<<1)+aarx][8], + idft(idftsizeidx,(int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset][(p<<1)+aarx][8], (int16_t *) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates_time[eNB_offset][(p<<1)+aarx],1); } } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c index 6f917ee49c..333a6f0866 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c @@ -724,31 +724,31 @@ int lte_dl_mbsfn_channel_estimation(PHY_VARS_UE *ue, if (ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa]) { switch (ue->frame_parms.N_RB_DL) { case 6: - idft128((int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], + idft(IDFT_128,(int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], (int16_t *) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_offset][aa], 1); break; case 25: - idft512((int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], + idft(IDFT_512,(int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], (int16_t *) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_offset][aa], 1); break; case 50: - idft1024((int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], + idft(IDFT_1024,(int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], (int16_t *) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_offset][aa], 1); break; case 75: - idft1536((int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], + idft(IDFT_1536,(int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], (int16_t *) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_offset][aa], 1); break; case 100: - idft2048((int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], + idft(IDFT_2048,(int16_t *) &ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates[eNB_offset][aa][8], (int16_t *) ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_offset][aa], 1); break; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c index 0c98bdc5a5..0d765a18b3 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c @@ -141,28 +141,28 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com switch (frame_parms->N_RB_DL) { case 6: - idft128((short*)syncF_tmp, /// complex input + idft(IDFT_128,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 25: - idft512((short*)syncF_tmp, /// complex input + idft(IDFT_512,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 50: - idft1024((short*)syncF_tmp, /// complex input + idft(IDFT_1024,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 75: - idft1536((short*)syncF_tmp, /// complex input + idft(IDFT_1536,(short*)syncF_tmp, /// complex input (short*)sync_tmp, 1); /// complex output break; case 100: - idft2048((short*)syncF_tmp, /// complex input + idft(IDFT_2048,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; @@ -189,28 +189,28 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com switch (frame_parms->N_RB_DL) { case 6: - idft128((short*)syncF_tmp, /// complex input + idft(IDFT_128,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 25: - idft512((short*)syncF_tmp, /// complex input + idft(IDFT_512,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 50: - idft1024((short*)syncF_tmp, /// complex input + idft(IDFT_1024,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 75: - idft1536((short*)syncF_tmp, /// complex input + idft(IDFT_1536,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 100: - idft2048((short*)syncF_tmp, /// complex input + idft(IDFT_2048,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; @@ -237,28 +237,28 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com switch (frame_parms->N_RB_DL) { case 6: - idft128((short*)syncF_tmp, /// complex input + idft(IDFT_128,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 25: - idft512((short*)syncF_tmp, /// complex input + idft(IDFT_512,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 50: - idft1024((short*)syncF_tmp, /// complex input + idft(IDFT_1024,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 75: - idft1536((short*)syncF_tmp, /// complex input + idft(IDFT_1536,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 100: - idft2048((short*)syncF_tmp, /// complex input + idft(IDFT_2048,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; @@ -492,28 +492,28 @@ int ru_sync_time_init(RU_t *ru) // LTE_UE_COMMON *common_vars switch (ru->frame_parms->N_RB_DL) { case 6: - idft128((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_128,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; case 25: - idft512((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_512,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; case 50: - idft1024((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_1024,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; case 75: - idft1536((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_1536,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, 1); /// complex output break; case 100: - idft2048((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_2048,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_timefreq.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_timefreq.c index de48a855df..524b200e1a 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_sync_timefreq.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_timefreq.c @@ -80,7 +80,7 @@ void lte_sync_timefreq(PHY_VARS_UE *ue,int band,unsigned int DL_freq) while (1) { //compute frequency-domain representation of 6144-sample chunk - dft6144((int16_t *)rxp, + dft(DFT_6144,(int16_t *)rxp, sp,1); @@ -267,7 +267,7 @@ void lte_sync_timefreq(PHY_VARS_UE *ue,int band,unsigned int DL_freq) } // ifft, accumulate energy over two half-frames - idft256((int16_t*)autocorr0,(int16_t*)tmp_t,1); + idft(IDFT_256,(int16_t*)autocorr0,(int16_t*)tmp_t,1); /* if (i==12288) { sprintf(fname,"corr256F_%d.m",abs(f)); @@ -285,12 +285,12 @@ void lte_sync_timefreq(PHY_VARS_UE *ue,int band,unsigned int DL_freq) for (re=0; re<(256/4); re++) autocorr0_t[re] = _mm_add_epi32(autocorr0_t[re],_mm_madd_epi16(tmp_t[re],tmp_t[re])); - idft256((int16_t*)autocorr1,(int16_t*)tmp_t,1); + idft(IDFT_256,(int16_t*)autocorr1,(int16_t*)tmp_t,1); for (re=0; re<(256/4); re++) autocorr1_t[re] = _mm_add_epi32(autocorr1_t[re],_mm_madd_epi16(tmp_t[re],tmp_t[re])); - idft256((int16_t*)autocorr2,(int16_t*)tmp_t,1); + idft(IDFT_256,(int16_t*)autocorr2,(int16_t*)tmp_t,1); for (re=0; re<(256/4); re++) autocorr2_t[re] = _mm_add_epi32(autocorr2_t[re],_mm_madd_epi16(tmp_t[re],tmp_t[re])); diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c index 2e4f3e6036..880c056578 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c @@ -1029,7 +1029,7 @@ void lte_ue_measurements(PHY_VARS_UE *ue, int N_RB_DL = frame_parms->N_RB_DL; - int rank_tm3_tm4; + int rank_tm3_tm4=-1; ue->measurements.nb_antennas_rx = frame_parms->nb_antennas_rx; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index cb001f9dc4..7caaf07406 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -50,8 +50,11 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, int32_t **ul_ch_estimates_time = (eNB!=NULL) ? pusch_vars->drs_ch_estimates_time : calibration->drs_ch_estimates_time; AssertFatal(ul_ch_estimates_time != NULL, "ul_ch_estimates_time is null\n"); int32_t **rxdataF_ext = (eNB!=NULL) ? pusch_vars->rxdataF_ext : calibration->rxdataF_ext; - int subframe = (eNB!=NULL) ? proc->subframe_rx : ru->proc.tti_rx; - uint8_t harq_pid; + + int subframe = proc->subframe_rx; + + uint8_t harq_pid; + int16_t delta_phase = 0; int16_t *ru1 = ru_90; int16_t *ru2 = ru_90; @@ -246,25 +249,25 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, switch(frame_parms->N_RB_DL) { case 6: - idft128((int16_t *) temp_in_ifft_0, + idft(IDFT_128,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 25: - idft512((int16_t *) temp_in_ifft_0, + idft(IDFT_512,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 50: - idft1024((int16_t *) temp_in_ifft_0, + idft(IDFT_1024,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 100: - idft2048((int16_t *) temp_in_ifft_0, + idft(IDFT_2048,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; @@ -575,25 +578,25 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, switch(frame_parms->N_RB_DL) { case 6: - idft128((int16_t *) temp_in_ifft_0, + idft(IDFT_128,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 25: - idft512((int16_t *) temp_in_ifft_0, + idft(IDFT_512,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 50: - idft1024((int16_t *) temp_in_ifft_0, + idft(IDFT_1024,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 100: - idft2048((int16_t *) temp_in_ifft_0, + idft(IDFT_2048,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 6595158f1a..15eb5206a1 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -20,15 +20,15 @@ */ /*! \file PHY/LTE_TRANSPORT/dlsch_coding.c -* \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 -* \author R. Knopp -* \date 2011 -* \version 0.1 -* \company Eurecom -* \email: knopp@eurecom.fr -* \note -* \warning -*/ + * \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 + * \author R. Knopp + * \date 2011 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr + * \note + * \warning + */ #include "PHY/defs_eNB.h" #include "PHY/phy_extern.h" @@ -42,22 +42,23 @@ #include "common/utils/LOG/log.h" #include "targets/RT/USER/lte-softmodem.h" #include -#include "executables/thread-common.h" +#include "targets/RT/USER/rt_wrapper.h" +#include //#define DEBUG_DLSCH_CODING //#define DEBUG_DLSCH_FREE 1 /* -#define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \ + #define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \ ((pilots==1)&&(first_pilot==1)&&(((re>2)&&(re<6))||((re>8)&&(re<12)))) || \ ((pilots==1)&&(first_pilot==0)&&(((re<3))||((re>5)&&(re<9)))) \ */ #define is_not_pilot(pilots,first_pilot,re) (1) /*extern void thread_top_init(char *thread_name, - int affinity, - uint64_t runtime, - uint64_t deadline, - uint64_t period);*/ + int affinity, + uint64_t runtime, + uint64_t deadline, + uint64_t period);*/ extern volatile int oai_exit; @@ -83,11 +84,6 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) { free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768); dlsch->harq_processes[i]->c[r] = NULL; } - - if (dlsch->harq_processes[i]->d[r]) { - free16(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); - dlsch->harq_processes[i]->d[r] = NULL; - } } free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t)); @@ -108,26 +104,26 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, LTE_DL_FRAME_PARMS *frame_parms) { LTE_eNB_DLSCH_t *dlsch; - unsigned char exit_flag = 0,i,j,r,aa,layer; + unsigned char exit_flag = 0,i,r,aa,layer; int re; unsigned char bw_scaling =1; switch (N_RB_DL) { - case 6: - bw_scaling =16; - break; + case 6: + bw_scaling =16; + break; - case 25: - bw_scaling =4; - break; + case 25: + bw_scaling =4; + break; - case 50: - bw_scaling =2; - break; + case 50: + bw_scaling =2; + break; - default: - bw_scaling =1; - break; + default: + bw_scaling =1; + break; } dlsch = (LTE_eNB_DLSCH_t *)malloc16(sizeof(LTE_eNB_DLSCH_t)); @@ -153,11 +149,11 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, // NOTE: THIS HAS TO BE REVISED FOR RU, commenting to remove memory leak !!!!! /* - dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); - for (aa=0; aanb_antennas_tx; aa++) { - dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); + dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); + for (aa=0; aanb_antennas_tx; aa++) { + dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - }*/ + }*/ for (i=0; i<20; i++) dlsch->harq_ids[i/10][i%10] = Mdlharq; @@ -183,7 +179,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, for (r=0; rharq_processes[i]->c[r] = (uint8_t *)malloc16(((r==0)?8:0) + 3+ 768); - dlsch->harq_processes[i]->d[r] = (uint8_t *)malloc16((96+12+3+(3*6144))); if (dlsch->harq_processes[i]->c[r]) { bzero(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+ 768); @@ -191,13 +186,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, printf("Can't get c\n"); exit_flag=2; } - - if (dlsch->harq_processes[i]->d[r]) { - bzero(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); - } else { - printf("Can't get d\n"); - exit_flag=2; - } } } } else { @@ -209,13 +197,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, if (exit_flag==0) { for (i=0; iharq_processes[i]->round=0; - - for (j=0; j<96; j++) - for (r=0; rharq_processes[%d]->d[%d] %p\n",i,r,dlsch->harq_processes[i]->d[r]); - if (dlsch->harq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = LTE_NULL; - } } return(dlsch); @@ -231,7 +212,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) { unsigned char Mdlharq; - unsigned char i,j,r; + unsigned char i; if (dlsch) { Mdlharq = dlsch->Mdlharq; @@ -255,307 +236,17 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) { dlsch->harq_processes[i]->status = 0; dlsch->harq_processes[i]->round = 0; - for (j=0; j<96; j++) - for (r=0; rharq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = LTE_NULL; } } } } - -int dlsch_encoding_2threads0(te_params *tep) { - LTE_eNB_DLSCH_t *dlsch = tep->dlsch; - unsigned int G = tep->G; - unsigned char harq_pid = tep->harq_pid; - unsigned int total_worker = tep->total_worker; - unsigned int current_worker = tep->current_worker; - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_IN); - - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet - for (r=(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*current_worker; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) { - if (rharq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - } - } - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - - for (r=0,r_offset=0; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) { - if(r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker)) { - int Nl=dlsch->harq_processes[harq_pid]->Nl; - int Qm=dlsch->harq_processes[harq_pid]->Qm; - int C = dlsch->harq_processes[harq_pid]->C; - int Gp = G/Nl/Qm; - int GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - r_offset += Nl*Qm * (Gp/C); - else - r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - } else { - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_OUT); - return(0); -} - - void *te_thread(void *param) { - te_params *tep = (te_params *)param; - - //wait_sync("te_thread"); - - while (!oai_exit) { - if (wait_on_condition(&tep->mutex_te,&tep->cond_te,&tep->instance_cnt_te,"te thread")<0) break; - - if(oai_exit) break; - - dlsch_encoding_2threads0(tep); - - if (release_thread(&tep->mutex_te,&tep->instance_cnt_te,"te thread")<0) break; - - if (pthread_cond_signal(&tep->cond_te) != 0) { - printf("[eNB] ERROR pthread_cond_signal for te thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(NULL); - } - - /*if(opp_enabled == 1 && te_wakeup_stats0->p_time>50*3000){ - print_meas_now(te_wakeup_stats0,"coding_wakeup",stderr); - printf("te_thread0 delay for waking up in frame_rx: %d subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx); - }*/ - } - return(NULL); } - -int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, - unsigned char *a, - uint8_t num_pdcch_symbols, - LTE_eNB_DLSCH_t *dlsch, - int frame, - uint8_t subframe, - time_stats_t *rm_stats, - time_stats_t *te_stats, - time_stats_t *te_wait_stats, - time_stats_t *te_main_stats, - time_stats_t *te_wakeup_stats0, - time_stats_t *te_wakeup_stats1, - time_stats_t *i_stats, - int worker_num) { - //start_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; - L1_proc_t *proc = &eNB->proc; - unsigned int G; - unsigned int crc=1; - unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe]; - if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) { - LOG_E(PHY,"dlsch_encoding_2threads illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__); - return(-1); - } - - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int A; - unsigned char mod_order; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); - A = dlsch->harq_processes[harq_pid]->TBS; //6228 - mod_order = dlsch->harq_processes[harq_pid]->Qm; - G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe, - dlsch->harq_processes[harq_pid]->mimo_mode==TM7?7:0); - - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet - start_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a, - A)>>8; - stop_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - a[A>>3] = ((uint8_t *)&crc)[2]; - a[1+(A>>3)] = ((uint8_t *)&crc)[1]; - a[2+(A>>3)] = ((uint8_t *)&crc)[0]; - dlsch->harq_processes[harq_pid]->B = A+24; - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); - //stop_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - start_meas(&eNB->dlsch_turbo_encoding_segmentation_stats); - - if (lte_segmentation(dlsch->harq_processes[harq_pid]->b, - dlsch->harq_processes[harq_pid]->c, - dlsch->harq_processes[harq_pid]->B, - &dlsch->harq_processes[harq_pid]->C, - &dlsch->harq_processes[harq_pid]->Cplus, - &dlsch->harq_processes[harq_pid]->Cminus, - &dlsch->harq_processes[harq_pid]->Kplus, - &dlsch->harq_processes[harq_pid]->Kminus, - &dlsch->harq_processes[harq_pid]->F)<0) - return(-1); - - stop_meas(&eNB->dlsch_turbo_encoding_segmentation_stats); - start_meas(&eNB->dlsch_turbo_encoding_signal_stats); - - for(int i=0; itep[i].eNB = eNB; - proc->tep[i].dlsch = dlsch; - proc->tep[i].G = G; - proc->tep[i].harq_pid = harq_pid; - proc->tep[i].total_worker = worker_num; - proc->tep[i].current_worker = i; - pthread_mutex_lock( &proc->tep[i].mutex_te ); - - if (proc->tep[i].instance_cnt_te==0) { - printf("[eNB] TE thread busy\n"); - exit_fun("TE thread busy"); - pthread_mutex_unlock( &proc->tep[i].mutex_te ); - return(-1); - } - - ++proc->tep[i].instance_cnt_te; - - // wakeup worker to do segments - if (pthread_cond_signal(&proc->tep[i].cond_te) != 0) { - printf("[eNB] ERROR pthread_cond_signal for te thread %d exit\n",i); - exit_fun( "ERROR pthread_cond_signal" ); - return (-1); - } - - pthread_mutex_unlock( &proc->tep[i].mutex_te ); - } - - stop_meas(&eNB->dlsch_turbo_encoding_signal_stats); - start_meas(te_main_stats); - - for (r=(dlsch->harq_processes[harq_pid]->C/(worker_num+1))*worker_num; rharq_processes[harq_pid]->C; r++) { - if (rharq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; - start_meas(te_stats); - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - stop_meas(te_stats); - start_meas(i_stats); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - stop_meas(i_stats); - } - } else { - for(int i=0; itep[i].eNB = eNB; - proc->tep[i].dlsch = dlsch; - proc->tep[i].G = G; - proc->tep[i].total_worker = worker_num; - proc->tep[i].current_worker = i; - - if (pthread_cond_signal(&proc->tep[i].cond_te) != 0) { - printf("[eNB] ERROR pthread_cond_signal for te thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return (-1); - } - } - } - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - for (r=0,r_offset=0; rharq_processes[harq_pid]->C; r++) { - // get information for E for the segments that are handled by the worker thread - if (r<(dlsch->harq_processes[harq_pid]->C/(worker_num+1))*worker_num) { - int Nl=dlsch->harq_processes[harq_pid]->Nl; - int Qm=dlsch->harq_processes[harq_pid]->Qm; - int C = dlsch->harq_processes[harq_pid]->C; - int Gp = G/Nl/Qm; - int GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - r_offset += Nl*Qm * (Gp/C); - else - r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - } else { - start_meas(rm_stats); - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - stop_meas(rm_stats); - } - } - - stop_meas(te_main_stats); - start_meas(te_wait_stats); - - if(worker_num == 1) { - wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0"); - } else if(worker_num == 2) { - wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0"); - wait_on_busy_condition(&proc->tep[1].mutex_te,&proc->tep[1].cond_te,&proc->tep[1].instance_cnt_te,"te thread 1"); - } else { - wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0"); - wait_on_busy_condition(&proc->tep[1].mutex_te,&proc->tep[1].cond_te,&proc->tep[1].instance_cnt_te,"te thread 1"); - wait_on_busy_condition(&proc->tep[2].mutex_te,&proc->tep[2].cond_te,&proc->tep[2].instance_cnt_te,"te thread 2"); - } - - stop_meas(te_wait_stats); - /*if(opp_enabled == 1 && te_wait_stats->p_time>100*3000){ - print_meas_now(te_wait_stats,"coding_wait",stderr); - printf("coding delay in wait on codition in frame_rx: %d \n",proc->frame_rx); - }*/ - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); - return(0); -} - - int dlsch_encoding_all(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -568,108 +259,72 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, time_stats_t *te_wakeup_stats0, time_stats_t *te_wakeup_stats1, time_stats_t *i_stats) { - int encoding_return = 0; - unsigned int L,C,B; uint8_t harq_pid = dlsch->harq_ids[frame%2][subframe]; if(harq_pid >= dlsch->Mdlharq) { LOG_E(PHY,"dlsch_encoding_all illegal harq_pid %d\n", harq_pid); return(-1); } - B = dlsch->harq_processes[harq_pid]->B; + + LOG_D(PHY,"B %d, harq_pid %d\n", + dlsch->harq_processes[harq_pid]->B, + dlsch->harq_ids[frame%2][subframe]); - LOG_D(PHY,"B %d, harq_pid %d\n",B,dlsch->harq_ids[frame%2][subframe]); + return dlsch_encoding(eNB, + proc, + a, + num_pdcch_symbols, + dlsch, + frame, + subframe, + rm_stats, + te_stats, + i_stats); - if(B<=6144) { - L=0; - C=1; - } else { - L=24; - C = B/(6144-L); - - if((6144-L)*C < B) { - C = C+1; - } - } - - if(get_thread_worker_conf() == WORKER_ENABLE) { - if(C >= 8) { //one main three worker - encoding_return = - dlsch_encoding_2threads(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - te_wait_stats, - te_main_stats, - te_wakeup_stats0, - te_wakeup_stats1, - i_stats, - 3); - } else if(C >= 6) { //one main two worker - encoding_return = - dlsch_encoding_2threads(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - te_wait_stats, - te_main_stats, - te_wakeup_stats0, - te_wakeup_stats1, - i_stats, - 2); - } else if(C >= 4) { //one main one worker - encoding_return = - dlsch_encoding_2threads(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - te_wait_stats, - te_main_stats, - te_wakeup_stats0, - te_wakeup_stats1, - i_stats, - 1); - } else { - encoding_return = - dlsch_encoding(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - i_stats); - } - } else { - encoding_return = - dlsch_encoding(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - i_stats); - } - - return encoding_return; } +static void TPencode(void * arg) { + turboEncode_t * rdata=(turboEncode_t *) arg; + unsigned char harq_pid = rdata->harq_pid; + LTE_DL_eNB_HARQ_t *hadlsch=rdata->dlsch->harq_processes[harq_pid]; + + if ( rdata-> round == 0) { + uint8_t tmp[96+12+3+3*6144]; + memset(tmp,LTE_NULL, TURBO_SIMD_SOFTBITS); + start_meas(rdata->te_stats); + encoder(rdata->input, + rdata->Kr_bytes, + tmp+96,//&dlsch->harq_processes[harq_pid]->d[r][96], + rdata->filler); + stop_meas(rdata->te_stats); + start_meas(rdata->i_stats); + hadlsch->RTC[rdata->r] = + sub_block_interleaving_turbo(4+(rdata->Kr_bytes*8), + tmp+96, + hadlsch->w[rdata->r]); + stop_meas(rdata->i_stats); + } + + // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the + // outputs for each code segment, see Section 5.1.5 p.20 + start_meas(rdata->rm_stats); + lte_rate_matching_turbo(hadlsch->RTC[rdata->r], + rdata->G, //G + hadlsch->w[rdata->r], + hadlsch->eDL+rdata->r_offset, + hadlsch->C, // C + rdata->dlsch->Nsoft, // Nsoft, + rdata->dlsch->Mdlharq, + rdata->dlsch->Kmimo, + hadlsch->rvidx, + hadlsch->Qm, + hadlsch->Nl, + rdata->r, + hadlsch->nb_rb); + stop_meas(rdata->rm_stats); +} int dlsch_encoding(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -678,8 +333,6 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, time_stats_t *rm_stats, time_stats_t *te_stats, time_stats_t *i_stats) { - unsigned int G; - unsigned int crc=1; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe]; if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) { @@ -687,135 +340,88 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, return(-1); } - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int A; - unsigned char mod_order; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; + LTE_DL_eNB_HARQ_t *hadlsch=dlsch->harq_processes[harq_pid]; uint8_t beamforming_mode=0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); - A = dlsch->harq_processes[harq_pid]->TBS; //6228 - // printf("Encoder: A: %d\n",A); - mod_order = dlsch->harq_processes[harq_pid]->Qm; - if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7) + if(hadlsch->mimo_mode == TM7) beamforming_mode = 7; - else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8) + else if(hadlsch->mimo_mode == TM8) beamforming_mode = 8; - else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10) + else if(hadlsch->mimo_mode == TM9_10) beamforming_mode = 9; - G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode); + unsigned int G = get_G(frame_parms,hadlsch->nb_rb, + hadlsch->rb_alloc, + hadlsch->Qm, // mod order + hadlsch->Nl, + num_pdcch_symbols, + frame,subframe,beamforming_mode); - // if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet -#ifdef DEBUG_DLSCH_CODING - printf("encoding thinks this is a new packet for harq_pid %d (%p), A %u \n",harq_pid,dlsch,A); -#endif - /* - int i; - printf("dlsch (tx): \n"); - for (i=0;i<(A>>3);i++) - printf("%02x.",a[i]); - printf("\n"); - */ + proc->nbEncode=0; + + // if (hadlsch->Ndi == 1) { // this is a new packet + if (hadlsch->round == 0) { // this is a new packet // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a, + unsigned int A=hadlsch->TBS; //6228; + unsigned int crc = crc24a(a, A)>>8; a[A>>3] = ((uint8_t *)&crc)[2]; a[1+(A>>3)] = ((uint8_t *)&crc)[1]; a[2+(A>>3)] = ((uint8_t *)&crc)[0]; // printf("CRC %x (A %d)\n",crc,A); - dlsch->harq_processes[harq_pid]->B = A+24; - // dlsch->harq_processes[harq_pid]->b = a; - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); - - if (lte_segmentation(dlsch->harq_processes[harq_pid]->b, - dlsch->harq_processes[harq_pid]->c, - dlsch->harq_processes[harq_pid]->B, - &dlsch->harq_processes[harq_pid]->C, - &dlsch->harq_processes[harq_pid]->Cplus, - &dlsch->harq_processes[harq_pid]->Cminus, - &dlsch->harq_processes[harq_pid]->Kplus, - &dlsch->harq_processes[harq_pid]->Kminus, - &dlsch->harq_processes[harq_pid]->F)<0) + hadlsch->B = A+24; + // hadlsch->b = a; + memcpy(hadlsch->b,a,(A/8)+4); + + if (lte_segmentation(hadlsch->b, + hadlsch->c, + hadlsch->B, + &hadlsch->C, + &hadlsch->Cplus, + &hadlsch->Cminus, + &hadlsch->Kplus, + &hadlsch->Kminus, + &hadlsch->F)<0) return(-1); - - for (r=0; rharq_processes[harq_pid]->C; r++) { - if (rharq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; -#ifdef DEBUG_DLSCH_CODING - printf("Generating Code Segment %u (%u bits)\n",r,Kr); - // generate codewords - printf("bits_per_codeword (Kr)= %u, A %u\n",Kr,A); - printf("N_RB = %d\n",nb_rb); - printf("Ncp %d\n",frame_parms->Ncp); - printf("mod_order %d\n",mod_order); -#endif - start_meas(te_stats); - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - stop_meas(te_stats); -#ifdef DEBUG_DLSCH_CODING - - if (r==0) - LOG_M("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4); - -#endif - start_meas(i_stats); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - stop_meas(i_stats); + } + + for (int r=0, r_offset=0; rC; r++) { + + union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, proc->respEncode, TPencode); + turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req); + rdata->input=hadlsch->c[r]; + rdata->Kr_bytes= ( rCminus ? hadlsch->Kminus : hadlsch->Kplus) >>3; + rdata->filler=(r==0) ? hadlsch->F : 0; + rdata->r=r; + rdata->harq_pid=harq_pid; + rdata->dlsch=dlsch; + rdata->rm_stats=rm_stats; + rdata->te_stats=te_stats; + rdata->i_stats=i_stats; + rdata->round=hadlsch->round; + rdata->r_offset=r_offset; + rdata->G=G; + + if ( proc->threadPool->activated ) { + pushTpool(proc->threadPool,req); + proc->nbEncode++; + } else { + TPencode(rdata); + delNotifiedFIFO_elt(req); } + + int Qm=hadlsch->Qm; + int C=hadlsch->C; + int Nl=hadlsch->Nl; + int Gp = G/Nl/Qm; + int GpmodC = Gp%C; + if (r < (C-(GpmodC))) + r_offset += Nl*Qm * (Gp/C); + else + r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); } - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - - for (r=0; rharq_processes[harq_pid]->C; r++) { -#ifdef DEBUG_DLSCH_CODING - printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - mod_order,nb_rb); -#endif - start_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - printf("rvidx in encoding = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - stop_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - - if (r==dlsch->harq_processes[harq_pid]->C-1) - LOG_M("enc_output.m","enc",dlsch->harq_processes[harq_pid]->e,r_offset,1,4); - -#endif - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return(0); } diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index 04a49d062a..475c8bd521 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -158,7 +158,7 @@ int allocate_REs_in_RB_no_pilots_QPSK_siso(PHY_VARS_eNB* phy_vars_eNB, { LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qpsk_table_offset_re = 0; uint32_t qpsk_table_offset_im = 0; @@ -248,7 +248,7 @@ int allocate_REs_in_RB_pilots_QPSK_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qpsk_table_offset_re = 0; uint32_t qpsk_table_offset_im = 0; @@ -343,7 +343,7 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, { LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam16_table_offset_re = 0; uint32_t qam16_table_offset_im = 0; @@ -439,7 +439,7 @@ int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam16_table_offset_re = 0; uint32_t qam16_table_offset_im = 0; @@ -542,7 +542,7 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam64_table_offset_re = 0; uint32_t qam64_table_offset_im = 0; @@ -699,7 +699,7 @@ int allocate_REs_in_RB_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam64_table_offset_re = 0; uint32_t qam64_table_offset_im = 0; @@ -866,12 +866,12 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, if ((dlsch0_harq != NULL) && (dlsch1_harq != NULL)) { //this is for TM3, TM4 - x0 = dlsch0_harq->e; + x0 = dlsch0_harq->eDL; mimo_mode = dlsch0_harq->mimo_mode; first_layer0 = dlsch0_harq->first_layer; Nlayers0 = dlsch0_harq->Nlayers; mod_order0 = dlsch0_harq->Qm; - x1 = dlsch1_harq->e; + x1 = dlsch1_harq->eDL; // Fill these in later for TM8-10 // Nlayers1 = dlsch1_harq->Nlayers; // first_layer1 = dlsch1_harq->first_layer; @@ -879,7 +879,7 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, } else if ((dlsch0_harq != NULL) && (dlsch1_harq == NULL)){ //This is for SIS0 TM1, TM6, etc - x0 = dlsch0_harq->e; + x0 = dlsch0_harq->eDL; mimo_mode = dlsch0_harq->mimo_mode; first_layer0 = dlsch0_harq->first_layer; Nlayers0 = dlsch0_harq->Nlayers; @@ -887,7 +887,7 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, } else if ((dlsch0_harq == NULL) && (dlsch1_harq != NULL)){ // This is for TM4 retransmission - x0 = dlsch1_harq->e; + x0 = dlsch1_harq->eDL; mimo_mode = dlsch1_harq->mimo_mode; first_layer0 = dlsch1_harq->first_layer; Nlayers0 = dlsch1_harq->Nlayers; @@ -2692,7 +2692,7 @@ int dlsch_modulation_SIC(int32_t **sic_buffer, LTE_DL_eNB_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid]; uint32_t i,jj,re_allocated=0; uint8_t mod_order0 = dlsch0_harq->Qm; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint8_t qam64_table_offset_re = 0; uint8_t qam64_table_offset_im = 0; uint8_t qam16_table_offset_re = 0; @@ -2883,7 +2883,7 @@ int mch_modulation(int32_t **txdataF, &jj, re_offset, symbol_offset, - dlsch->harq_processes[0]->e, + dlsch->harq_processes[0]->eDL, l, mod_order, amp, diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c index 2e8ddde848..d48164e07d 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c @@ -52,7 +52,7 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, int n; // uint8_t reset; uint32_t x1, x2, s=0; - uint8_t *dlsch_e=dlsch->harq_processes[harq_pid]->e; + uint8_t *dlsch_e=dlsch->harq_processes[harq_pid]->eDL; uint8_t *e=dlsch_e; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, VCD_FUNCTION_IN); // Rule for accumulation of subframes for BL/CE UEs diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.h b/openair1/PHY/LTE_TRANSPORT/if5_tools.h index 0f24f7bece..6c75b20bd9 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.h @@ -61,7 +61,8 @@ typedef struct IF5_mobipass_header IF5_mobipass_header_t; void send_IF5(RU_t *, openair0_timestamp, int, uint8_t*, uint16_t); -void recv_IF5(RU_t *, openair0_timestamp*, int, uint16_t); +void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type); + void malloc_IF5_buffer(RU_t *ru); diff --git a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c index c13876f29a..6144b978bf 100644 --- a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c +++ b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c @@ -94,6 +94,35 @@ unsigned char I_TBS2I_MCS(unsigned char I_TBS) { return I_MCS; } +uint16_t find_nb_rb_DL(uint8_t mcs, uint32_t bytes, uint16_t nb_rb_max, uint16_t rb_gran) { + if (bytes == 0 || mcs > 28 || nb_rb_max == 0) + return 0; + const uint32_t bits = bytes << 3; + const unsigned char I_TBS = get_I_TBS(mcs); + + uint32_t TBS = TBStable[I_TBS][nb_rb_max - 1]; + if (bits >= TBS) // is nb_rb_max too small? + return nb_rb_max; + + TBS = TBStable[I_TBS][rb_gran - 1]; + if (bits <= TBS) // is rb_gran RB enough? + return rb_gran; + + nb_rb_max += nb_rb_max % rb_gran; // round up to full RBG + uint16_t hi = nb_rb_max/rb_gran - 1; + uint16_t lo = 0; + uint16_t p = (hi + lo) / 2; + for (; lo + 1 != hi; p = (hi + lo) / 2) { + const uint16_t rbi = (p + 1) * rb_gran - 1; // convert "RBG" -> RB + TBS = TBStable[I_TBS][rbi]; + if (bits <= TBS) // need less RBs + hi = p; + else // need more RBs + lo = p; + } + return (hi + 1) * rb_gran; +} + uint32_t get_TBS_DL(uint8_t mcs, uint16_t nb_rb) { uint32_t TBS; diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index ab2fe2d743..6d8b58818b 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -714,7 +714,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, int32_t **txdataF = eNB->common_vars.txdataF; uint8_t Ngroup_PHICH,ngroup_PHICH,nseq_PHICH; uint8_t NSF_PHICH = 4; - uint8_t pusch_subframe; + uint8_t pusch_subframe=-1; uint8_t i; int subframe = proc->subframe_tx; phich_config_t *phich; diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index f48ee629a1..90e2836b1e 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -105,6 +105,7 @@ void generate_mch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,uint8_t *a) AssertFatal(eNB->dlsch_MCH->harq_processes[0]->pdu != NULL, "attempt to encode a NULL harq PDU\n"); AssertFatal(dlsch_encoding(eNB, + proc, // a, eNB->dlsch_MCH->harq_processes[0]->pdu, 1, diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 3471f98af7..24faf584d3 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -38,9 +38,13 @@ #include "SCHED/sched_eNB.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "prach_extern.h" +#include +#include void rx_prach0(PHY_VARS_eNB *eNB, RU_t *ru, + int frame_prach, + int subframe, uint16_t *max_preamble, uint16_t *max_preamble_energy, uint16_t *max_preamble_delay, @@ -51,17 +55,14 @@ void rx_prach0(PHY_VARS_eNB *eNB, uint8_t ce_level ) { int i; - LTE_DL_FRAME_PARMS *fp=NULL; lte_frame_type_t frame_type; uint16_t rootSequenceIndex; uint8_t prach_ConfigIndex; uint8_t Ncs_config; uint8_t restricted_set; uint8_t n_ra_prb; - int subframe; int16_t *prachF=NULL; int16_t **rxsigF=NULL; - int nb_rx=0; int16_t *prach2; uint8_t preamble_index; uint16_t NCS,NCS2; @@ -89,6 +90,8 @@ void rx_prach0(PHY_VARS_eNB *eNB, int32_t **prach_ifftp=(int32_t **)NULL; int prach_ifft_cnt=0; + LTE_DL_FRAME_PARMS *fp; + int nb_rx; if(eNB) { fp = &(eNB->frame_parms); nb_rx = fp->nb_antennas_rx; @@ -96,7 +99,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, fp = (ru->frame_parms); nb_rx = ru->nb_rx; } - + AssertFatal(fp!=NULL,"rx_prach called without valid RU or eNB descriptor\n"); frame_type = fp->frame_type; @@ -133,14 +136,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (eNB) { if (br_flag == 1) { prach_ifftp = eNB->prach_vars_br.prach_ifft[ce_level]; - subframe = eNB->proc.subframe_prach_br; prachF = eNB->prach_vars_br.prachF; rxsigF = eNB->prach_vars_br.rxsigF[ce_level]; if (LOG_DEBUGFLAG(PRACH)) { - if (((eNB->proc.frame_prach)&1023) < 20) LOG_I(PHY, + if (((frame_prach)&1023) < 20) LOG_I(PHY, "PRACH (eNB) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d, rootSequenceIndex %d, repetition number %d,numRepetitionsPrePreambleAttempt %d\n", - br_flag,ce_level,eNB->proc.frame_prach,subframe, + br_flag,ce_level,frame_prach,subframe, fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level], prach_ConfigIndex,rootSequenceIndex, eNB->prach_vars_br.repetition_number[ce_level], @@ -148,30 +150,27 @@ void rx_prach0(PHY_VARS_eNB *eNB, } } else { prach_ifftp = eNB->prach_vars.prach_ifft[0]; - subframe = eNB->proc.subframe_prach; prachF = eNB->prach_vars.prachF; rxsigF = eNB->prach_vars.rxsigF[0]; if (LOG_DEBUGFLAG(PRACH)) { - if (((eNB->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (eNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d\n", subframe, + if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (eNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d\n", subframe, fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex,rootSequenceIndex); } } } else { if (br_flag == 1) { - subframe = ru->proc.subframe_prach_br; rxsigF = ru->prach_rxsigF_br[ce_level]; if (LOG_DEBUGFLAG(PRACH)) { - if (((ru->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", - br_flag,ce_level,ru->proc.frame_prach,subframe,fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level],prach_ConfigIndex); + if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", + br_flag,ce_level,frame_prach,subframe,fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level],prach_ConfigIndex); } } else { - subframe = ru->proc.subframe_prach; rxsigF = ru->prach_rxsigF; if (LOG_DEBUGFLAG(PRACH)) { - if (((ru->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", + if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex); } } @@ -202,7 +201,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (prach[0]!= NULL) LOG_M("prach_rx","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,ru->proc.frame_prach,subframe,fp->samples_per_tti, + 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], (subframe*fp->samples_per_tti)-ru->N_TA_offset); } @@ -298,24 +297,24 @@ void rx_prach0(PHY_VARS_eNB *eNB, switch (fp->N_RB_UL) { case 6: if (prach_fmt == 4) { - dft256(prach2,rxsigF[aa],1); + dft(DFT_256,prach2,rxsigF[aa],1); } else { - dft1536(prach2,rxsigF[aa],1); + dft(DFT_1536,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft1536(prach2+3072,rxsigF[aa]+3072,1); + dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); } break; case 15: if (prach_fmt == 4) { - dft256(prach2,rxsigF[aa],1); + dft(DFT_256,prach2,rxsigF[aa],1); } else { - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft3072(prach2+6144,rxsigF[aa]+6144,1); + dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); } break; @@ -323,13 +322,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 25: default: if (prach_fmt == 4) { - dft1024(prach2,rxsigF[aa],1); + dft(DFT_1024,prach2,rxsigF[aa],1); fft_size = 1024; } else { - dft6144(prach2,rxsigF[aa],1); + dft(DFT_6144,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft6144(prach2+12288,rxsigF[aa]+12288,1); + dft(DFT_6144,prach2+12288,rxsigF[aa]+12288,1); fft_size = 6144; } @@ -338,24 +337,24 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 50: if (prach_fmt == 4) { - dft2048(prach2,rxsigF[aa],1); + dft(DFT_2048,prach2,rxsigF[aa],1); } else { - dft12288(prach2,rxsigF[aa],1); + dft(DFT_12288,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft12288(prach2+24576,rxsigF[aa]+24576,1); + dft(DFT_12288,prach2+24576,rxsigF[aa]+24576,1); } break; case 75: if (prach_fmt == 4) { - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); } else { - dft18432(prach2,rxsigF[aa],1); + dft(DFT_18432,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft18432(prach2+36864,rxsigF[aa]+36864,1); + dft(DFT_18432,prach2+36864,rxsigF[aa]+36864,1); } break; @@ -363,21 +362,21 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 100: if (fp->threequarter_fs==0) { if (prach_fmt == 4) { - dft4096(prach2,rxsigF[aa],1); + dft(DFT_4096,prach2,rxsigF[aa],1); } else { - dft24576(prach2,rxsigF[aa],1); + dft(DFT_24576,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft24576(prach2+49152,rxsigF[aa]+49152,1); + dft(DFT_24576,prach2+49152,rxsigF[aa]+49152,1); } } else { if (prach_fmt == 4) { - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); } else { - dft18432(prach2,rxsigF[aa],1); + dft(DFT_18432,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft18432(prach2+36864,rxsigF[aa]+36864,1); + dft(DFT_18432,prach2+36864,rxsigF[aa]+36864,1); } } @@ -407,16 +406,16 @@ void rx_prach0(PHY_VARS_eNB *eNB, if ((eNB==NULL) && ru->function == NGFI_RRU_IF4p5) { /// **** send_IF4 of rxsigF to RAU **** /// if (br_flag == 1) - send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH+1+ce_level); + send_IF4p5(ru, frame_prach, subframe, IF4p5_PRACH+1+ce_level); else - send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH); + send_IF4p5(ru, frame_prach, subframe, IF4p5_PRACH); return; } else if (eNB!=NULL) { 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,eNB->proc.frame_rx,eNB->proc.subframe_rx,en); + 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); } } @@ -457,7 +456,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) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",ru->proc.frame_prach,subframe,preamble_index,br_flag); + 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 (restricted_set == 0) { @@ -543,7 +542,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, int 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", - ru->proc.frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,en); + frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,en); } log2_ifft_size = 10; @@ -589,13 +588,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) if (N_ZC == 839) { log2_ifft_size = 10; - idft1024(prachF,prach_ifft_tmp,1); + idft(IDFT_1024,prachF,prach_ifft_tmp,1); // compute energy and accumulate over receive antennas and repetitions for BR for (i=0; i<2048; i++) prach_ifft[i] += (prach_ifft_tmp[i<<1]*prach_ifft_tmp[i<<1] + prach_ifft_tmp[1+(i<<1)]*prach_ifft_tmp[1+(i<<1)])>>9; } else { - idft256(prachF,prach_ifft_tmp,1); + idft(IDFT_256,prachF,prach_ifft_tmp,1); log2_ifft_size = 8; // compute energy and accumulate over receive antennas and repetitions for BR @@ -618,7 +617,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) LOG_I(PHY,"frame %d, subframe %d: Checking for peak in time-domain (br_flag %d, en %d)\n",ru->proc.frame_prach,subframe,br_flag,en); + if (en>60) LOG_I(PHY,"frame %d, subframe %d: Checking for peak in time-domain (br_flag %d, en %d)\n",frame_prach,subframe,br_flag,en); } preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<60) && (br_flag==1)) 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", - ru->proc.frame_prach,subframe, + frame_prach,subframe, *max_preamble_energy,*max_preamble_delay, *max_preamble,br_flag,ce_level,levdB,lev); } @@ -694,8 +693,16 @@ void rx_prach(PHY_VARS_eNB *eNB, int i; int prach_mask=0; + int subframe; + if (eNB) + subframe= br_flag?eNB->proc.subframe_prach_br:eNB->proc.subframe_prach; + else + subframe= br_flag?ru->proc.subframe_prach_br:ru->proc.subframe_prach; + + int frame_prach=eNB?eNB->proc.frame_prach: ru->proc.frame_prach; + if (br_flag == 0) { - rx_prach0(eNB,ru,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); + rx_prach0(eNB,ru,frame_prach,subframe,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); } else { // This is procedure for eMTC, basically handling the repetitions prach_mask = is_prach_subframe(&eNB->frame_parms,eNB->proc.frame_prach_br,eNB->proc.subframe_prach_br); @@ -709,7 +716,7 @@ void rx_prach(PHY_VARS_eNB *eNB, // increment repetition number eNB->prach_vars_br.repetition_number[i]++; // do basic PRACH reception - rx_prach0(eNB,ru,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); + rx_prach0(eNB,ru,frame_prach,subframe,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); // if last repetition, clear counter if (eNB->prach_vars_br.repetition_number[i] == eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[i]) { diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index e142d2f29f..8637e80137 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -180,7 +180,7 @@ uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX uint16_t n3_pucch_array[NUMBER_OF_UE_MAX], uint8_t ncs_cell[20][7] ) { uint32_t aa, symNo, k, slotNo, sym, i, j; - int16_t np, np_n, ip_ind; + int16_t np, np_n, ip_ind=-1; //int16_t npucch_sf; int16_t calctmp[2]; int16_t BsCshData[NB_ANTENNAS_RX][D_NSYM1SF][D_NSC1RB][2]; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h index 1d7aa598af..e4f5d9a17f 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h @@ -60,6 +60,8 @@ unsigned char get_I_TBS_UL(unsigned char I_MCS); @return Transport block size */ uint32_t get_TBS_DL(uint8_t mcs, uint16_t nb_rb); +uint16_t find_nb_rb_DL(uint8_t mcs, uint32_t bytes, uint16_t nb_rb_max, uint16_t rb_gran); + /** \brief Compute Q (modulation order) based on uplink I_MCS. Implements table 7.1.7.1-1 from 36.213. @param I_MCS @param nb_rb diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 7b9004ba80..5e446db5fd 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -100,7 +100,7 @@ typedef struct { /// start symbold of pdsch uint8_t pdsch_start; /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) - uint8_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); + uint8_t eDL[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Turbo-code outputs (36-212 V8.6 2009-03, p.12 uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; /// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17) @@ -261,12 +261,13 @@ typedef struct { /// coded RI bits int16_t q_RI[MAX_RI_PAYLOAD]; /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) - int16_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); + int16_t eUL[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Temporary h sequence to flag PUSCH_x/PUSCH_y symbols which are not scrambled uint8_t h[MAX_NUM_CHANNEL_BITS]; /// Pointer to the payload - uint8_t *b; + uint8_t *decodedBytes; /// Pointers to transport block segments + //TBD uint8_t *c[MAX_NUM_ULSCH_SEGMENTS]; /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15) uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS]; @@ -282,8 +283,12 @@ typedef struct { uint8_t rvidx; /// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) int16_t w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; + int16_t pusch_rep_buffer[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) + //TBD int16_t *d[MAX_NUM_ULSCH_SEGMENTS]; + uint32_t processedSegments; + uint32_t processedBadSegment; /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9) uint32_t C; /// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10) diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h index f034039e7e..3988923bb9 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h @@ -73,18 +73,19 @@ void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch); LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag); int dlsch_encoding_all(PHY_VARS_eNB *eNB, - unsigned char *a, - uint8_t num_pdcch_symbols, - LTE_eNB_DLSCH_t *dlsch, - int frame, - uint8_t subframe, - time_stats_t *rm_stats, - time_stats_t *te_stats, - time_stats_t *te_wait_stats, - time_stats_t *te_main_stats, - time_stats_t *te_wakeup_stats0, - time_stats_t *te_wakeup_stats1, - time_stats_t *i_stats); + L1_rxtx_proc_t *proc, + unsigned char *a, + uint8_t num_pdcch_symbols, + LTE_eNB_DLSCH_t *dlsch, + int frame, + uint8_t subframe, + time_stats_t *rm_stats, + time_stats_t *te_stats, + time_stats_t *te_wait_stats, + time_stats_t *te_main_stats, + time_stats_t *te_wakeup_stats0, + time_stats_t *te_wakeup_stats1, + time_stats_t *i_stats); /** \fn dlsch_encoding(PHY_VARS_eNB *eNB, uint8_t *input_buffer, @@ -112,6 +113,7 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, @returns status */ int32_t dlsch_encoding(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, uint8_t *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -467,9 +469,12 @@ void rx_ulsch(PHY_VARS_eNB *eNB, int ulsch_decoding_data_all(PHY_VARS_eNB *eNB, - int UE_id, - int harq_pid, - int llr8_flag); + + L1_rxtx_proc_t *proc, + int UE_id, + int harq_pid, + int llr8_flag); + /*! \brief Decoding of PUSCH/ACK/RI/ACK from 36-212. @@ -511,6 +516,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB, @returns 0 on success */ int ulsch_decoding_data(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, int UE_id, int harq_pid, int llr8_flag); diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 39556902fc..90492b9999 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -41,22 +41,22 @@ #include "RRC/LTE/rrc_extern.h" #include "PHY_INTERFACE/phy_interface.h" #include "transport_proto.h" -#include "common/utils/LOG/vcd_signal_dumper.h" - +#include extern WORKER_CONF_t get_thread_worker_conf(void); extern volatile int oai_exit; + void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch) { int i,r; if (ulsch) { for (i=0; i<8; i++) { if (ulsch->harq_processes[i]) { - if (ulsch->harq_processes[i]->b) { - free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); - ulsch->harq_processes[i]->b = NULL; + if (ulsch->harq_processes[i]->decodedBytes) { + free16(ulsch->harq_processes[i]->decodedBytes,MAX_ULSCH_PAYLOAD_BYTES); + ulsch->harq_processes[i]->decodedBytes = NULL; } for (r=0; rharq_processes[i]) { memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t)); - ulsch->harq_processes[i]->b = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + ulsch->harq_processes[i]->decodedBytes = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); - if (ulsch->harq_processes[i]->b) - memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + if (ulsch->harq_processes[i]->decodedBytes) + memset(ulsch->harq_processes[i]->decodedBytes,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); else exit_flag=3; @@ -210,388 +210,26 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) { return(crc); } - - - -int ulsch_decoding_data_2thread0(td_params *tdp) { - PHY_VARS_eNB *eNB = tdp->eNB; - int UE_id = tdp->UE_id; - int harq_pid = tdp->harq_pid; - int llr8_flag = tdp->llr8_flag; - unsigned int r,r_offset=0,Kr,Kr_bytes; - uint8_t crc_type; - int offset = 0; - int ret = 1; - int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; - LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; - LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - int Q_m = ulsch_harq->Qm; - int G = ulsch_harq->G; - uint32_t E=0; - uint32_t Gp,GpmodC,Nl=1; - uint32_t C = ulsch_harq->C; - decoder_if_t *tc; - - if (llr8_flag == 0) - tc = decoder16; - else - tc = decoder8; - - // go through first half of segments to get r_offset - for (r=0; r<(ulsch_harq->C/2); r++) { - // Get Turbo interleaver parameters - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - // This is stolen from rate-matching algorithm to get the value of E - Gp = G/Nl/Q_m; - GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - E = Nl*Q_m * (Gp/C); - else - E = Nl*Q_m * ((GpmodC==0?0:1) + (Gp/C)); - - r_offset += E; - - if (r==0) { - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } - - // go through second half of segments - for (; r<(ulsch_harq->C); r++) { - // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); - // Get Turbo interleaver parameters - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), - (uint8_t *)&dummy_w[r][0], +void processULSegment(void * arg) { + turboDecode_t* rdata=(turboDecode_t*) arg; + PHY_VARS_eNB *eNB=rdata->eNB; + LTE_UL_eNB_HARQ_t *ulsch_harq=rdata->ulsch_harq; + int r=rdata->segment_r; + int G=ulsch_harq->G; + int Kr_bytes=rdata->Kr>>3; + int16_t dummy_w[3*(6144+64)]; + + memset(&dummy_w[0],0,3*(6144+64)*sizeof(short)); + ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), + (uint8_t *)&dummy_w[0], (r==0) ? ulsch_harq->F : 0); -#ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n", - r, G, - Kr*3, - Q_m, - nb_rb, - ulsch_harq->Nl); -#endif - - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], - G, - ulsch_harq->w[r], - (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, - ulsch_harq->C, - NSOFT, - 0, //Uplink - 1, - ulsch_harq->rvidx, - (ulsch_harq->round==0)?1:0, // clear - ulsch_harq->Qm, - 1, - r, - &E)==-1) { - LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return(-1); - } - - r_offset += E; - sub_block_deinterleaving_turbo(4+Kr, - &ulsch_harq->d[r][96], - ulsch_harq->w[r]); - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } else { - break; - } - } - - return(ret); -} - - -void *td_thread(void *param) { - PHY_VARS_eNB *eNB = ((td_params *)param)->eNB; - L1_proc_t *proc = &eNB->proc; - pthread_setname_np( pthread_self(),"td processing"); - LOG_I(PHY,"thread td created id=%ld\n", syscall(__NR_gettid)); - //wait_sync("td_thread"); - - while (!oai_exit) { - if (wait_on_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread")<0) break; - - if(oai_exit) break; - - ((td_params *)param)->ret = ulsch_decoding_data_2thread0((td_params *)param); - - if (release_thread(&proc->mutex_td,&proc->instance_cnt_td,"td thread")<0) break; - - if (pthread_cond_signal(&proc->cond_td) != 0) { - printf("[eNB] ERROR pthread_cond_signal for td thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(NULL); - } - } - - return(NULL); -} - -int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { - L1_proc_t *proc = &eNB->proc; - unsigned int r,r_offset=0,Kr,Kr_bytes; - uint8_t crc_type; - int offset = 0; - int ret = 1; - int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; - LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; - LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - int G = ulsch_harq->G; + start_meas(&eNB->ulsch_deinterleaving_stats); unsigned int E; - int Cby2; - decoder_if_t *tc; - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - if (llr8_flag == 0) - tc = decoder16; - else - tc = decoder8; - - if (ulsch_harq->C>1) { // wakeup worker if more than 1 segment - if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) { - printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td); - exit_fun( "error locking mutex_fep" ); - return -1; - } - - if (proc->instance_cnt_td==0) { - printf("[eNB] TD thread busy\n"); - exit_fun("TD thread busy"); - pthread_mutex_unlock( &proc->mutex_td ); - return -1; - } - - ++proc->instance_cnt_td; - proc->tdp.eNB = eNB; - proc->tdp.UE_id = UE_id; - proc->tdp.harq_pid = harq_pid; - proc->tdp.llr8_flag = llr8_flag; - - // wakeup worker to do second half segments - if (pthread_cond_signal(&proc->cond_td) != 0) { - printf("[eNB] ERROR pthread_cond_signal for td thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return (1+ulsch->max_turbo_iterations); - } - - pthread_mutex_unlock( &proc->mutex_td ); - Cby2 = ulsch_harq->C/2; - } else { - Cby2 = 1; - } - - // go through first half of segments in main thread - for (r=0; rc[r]); - // Get Turbo interleaver parameters - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), - (uint8_t *)&dummy_w[r][0], - (r==0) ? ulsch_harq->F : 0); -#ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n", - r, G, - Kr*3, - Q_m, - nb_rb, - ulsch_harq->Nl); -#endif - start_meas(&eNB->ulsch_rate_unmatching_stats); - - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], + if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], G, ulsch_harq->w[r], - (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, - ulsch_harq->C, - NSOFT, - 0, //Uplink - 1, - ulsch_harq->rvidx, - (ulsch_harq->round==0)?1:0, // clear - ulsch_harq->Qm, - 1, - r, - &E)==-1) { - LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return(-1); - } - - stop_meas(&eNB->ulsch_rate_unmatching_stats); - r_offset += E; - start_meas(&eNB->ulsch_deinterleaving_stats); - sub_block_deinterleaving_turbo(4+Kr, - &ulsch_harq->d[r][96], - ulsch_harq->w[r]); - stop_meas(&eNB->ulsch_deinterleaving_stats); - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - start_meas(&eNB->ulsch_turbo_decoding_stats); - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - - if (r==0) { - memcpy(ulsch_harq->b, - &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } else { - break; - } - - stop_meas(&eNB->ulsch_turbo_decoding_stats); - //printf("/////////////////////////////////////////**************************loop for %d time in ulsch_decoding main\n",r); - } - - // wait for worker to finish - wait_on_busy_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread"); - return( (ret>proc->tdp.ret) ? ret : proc->tdp.ret ); -} - -int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { - unsigned int r,r_offset=0,Kr,Kr_bytes; - uint8_t crc_type; - int offset = 0; - int ret = 1; - int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; - LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; - LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - int G = ulsch_harq->G; - unsigned int E; - decoder_if_t *tc; - static int32_t pusch_rep_buffer[3*(6144+64)]; - int max_Ncb; - - if (llr8_flag == 0) - tc = *decoder16; - else - tc = *decoder8; - - if(ulsch_harq->repetition_number == 1) { - memset(pusch_rep_buffer,0,(sizeof(int32_t)*3*(6144+64))) ; // reset the buffer every new repetitions - } - - for (r=0; rC; r++) { - // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); - // Get Turbo interleaver parameters - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), - (uint8_t *)&dummy_w[r][0], - (r==0) ? ulsch_harq->F : 0); -#ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d)...\n", - r, G, - Kr*3, - ulsch_harq->Qm, - ulsch_harq->Nl); -#endif - start_meas(&eNB->ulsch_rate_unmatching_stats); - - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], - G, - ulsch_harq->w[r], - (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, + (uint8_t *) &dummy_w[0], + ulsch_harq->eUL+rdata->r_offset, ulsch_harq->C, NSOFT, 0, //Uplink @@ -603,97 +241,132 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) r, &E)==-1) { LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return(-1); + return; + } + stop_meas(&eNB->ulsch_rate_unmatching_stats); + int max_Ncb = 3*ulsch_harq->RTC[r]*32 ; + + if(ulsch_harq->repetition_number == 1) { + memset(ulsch_harq->pusch_rep_buffer[r],0,(sizeof(int32_t)*3*(6144+64))) ; // reset the buffer every new repetitions + } + if(ulsch_harq->total_number_of_repetitions > 1) { + if (ulsch_harq->rvidx==1) { + LOG_E(PHY,"Adding HARQ data for segment: %d\n", r); + // Store the result of HARQ combining in the last emtc repetitions of sequence 0,2,3,1 + for (int nn=0; nnpusch_rep_buffer[r][nn] += ulsch_harq->w[r][nn] ; } - stop_meas(&eNB->ulsch_rate_unmatching_stats); - max_Ncb = 3*ulsch_harq->RTC[r]*32 ; - - if(ulsch_harq->total_number_of_repetitions > 1) { - if (ulsch_harq->rvidx==1) { - // Store the result of HARQ combining in the last emtc repetitions of sequence 0,2,3,1 - for (int nn=0; nnw[r][nn] ; - } - } - - if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions) { - for (int nn=0; nnw[r][nn] = pusch_rep_buffer[nn] ; - } - } - } - - r_offset += E; - start_meas(&eNB->ulsch_deinterleaving_stats); - sub_block_deinterleaving_turbo(4+Kr, - &ulsch_harq->d[r][96], - ulsch_harq->w[r]); - stop_meas(&eNB->ulsch_deinterleaving_stats); - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - start_meas(&eNB->ulsch_turbo_decoding_stats); - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - stop_meas(&eNB->ulsch_turbo_decoding_stats); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - - if (r==0) { - memcpy(ulsch_harq->b, - &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } else { - break; + if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions) { + LOG_E(PHY,"Will use HARQ data sum up for segment: %d\n", r); + for (int nn=0; nnw[r][nn] = ulsch_harq->pusch_rep_buffer[r][nn] ; } } + int16_t soft_bits[3*8*6144+12+96] __attribute__((aligned(32))); + sub_block_deinterleaving_turbo(4+rdata->Kr, + soft_bits+96, + ulsch_harq->w[r]); + stop_meas(&eNB->ulsch_deinterleaving_stats); + rdata->decodeIterations = rdata->function( soft_bits+96, + NULL, + rdata->decoded_bytes, + NULL, + rdata->Kr, + rdata->maxIterations, + rdata->nbSegments == 1 ? CRC24_A: CRC24_B, + rdata->Fbits, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); + stop_meas(&eNB->ulsch_turbo_decoding_stats); + +} +void *td_thread(void *param) { + + return(NULL); +} + +int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, + int UE_id,int harq_pid,int llr8_flag) { + unsigned int r_offset=0; + int offset = 0; + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + int G = ulsch_harq->G; + unsigned int E; + int ret=0; + + decoder_if_t * td=llr8_flag == 0 ? + *decoder16 : *decoder8; + ulsch_harq->processedSegments=0; + + for (int r=0; rC; r++) { + // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); + // Get Turbo interleaver parameters + unsigned int Kr= rCminus ? + ulsch_harq->Kminus :ulsch_harq->Kplus; + unsigned int Kr_bytes = Kr>>3; + +#ifdef DEBUG_ULSCH_DECODING + printf("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d, r_offset %u)...\n", + r, G, + Kr*3, + ulsch_harq->Qm, + ulsch_harq->Nl, r_offset); +#endif + int Gp=G/ulsch_harq->Qm; + int GpmodC = Gp%ulsch_harq->C; + + if (r < (ulsch_harq->C-(GpmodC))) + E = ulsch_harq->Qm * (Gp/ulsch_harq->C); + else + E = ulsch_harq->Qm * ((GpmodC==0?0:1) + (Gp/ulsch_harq->C)); + + if ( split73 == SPLIT73_DU ) { + sendFs6Ul(eNB, UE_id, harq_pid, r, ulsch_harq->eUL+r_offset, E*sizeof(int16_t), r_offset); + r_offset += E; + continue; + } + + union turboReqUnion id= {.s={ulsch->rnti,proc->frame_rx,proc->subframe_rx,0,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboDecode_t), id.p, proc->respDecode, processULSegment); + turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); + + rdata->eNB=eNB; + rdata->frame=proc->frame_rx; + rdata->subframe=proc->subframe_rx; + rdata->UEid=UE_id; + rdata->harq_pid=harq_pid; + rdata->Kr=Kr; + rdata->maxIterations=eNB->ulsch[UE_id]->max_turbo_iterations; + rdata->ulsch_harq=ulsch_harq; + rdata->eNB=eNB; + rdata->nbSegments=ulsch_harq->C; + rdata->segment_r=r; + rdata->Fbits=(r==0) ? ulsch_harq->F : 0; + rdata->r_offset=r_offset; + rdata->offset=offset; + rdata->function=td; + int Fbytes=(r==0) ? rdata->Fbits>>3 : 0; + int sz=Kr_bytes - Fbytes - ((ulsch_harq->C>1)?3:0); + pushTpool(proc->threadPool,req); + proc->nbDecode++; + LOG_D(PHY,"Added a block to decode, in pipe: %d\n",proc->nbDecode); + r_offset+=E; + offset+=sz; + } return(ret); } -int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { - int ret = 0; - /*if(get_thread_worker_conf() == WORKER_ENABLE) - { - ret = ulsch_decoding_data_2thread(eNB,UE_id,harq_pid,llr8_flag); - } - else*/ - { - ret = ulsch_decoding_data(eNB,UE_id,harq_pid,llr8_flag); - } - return ret; +int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, + int UE_id,int harq_pid,int llr8_flag) { + return ulsch_decoding_data(eNB,proc,UE_id,harq_pid,llr8_flag); } static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline)); @@ -767,7 +440,6 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, else harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1); // x1 is set in lte_gold_generic x2 = ((uint32_t)ulsch->rnti<<14) + ((uint32_t)subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1 ulsch_harq = ulsch->harq_processes[harq_pid]; @@ -779,8 +451,9 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, A = ulsch_harq->TBS; Q_m = ulsch_harq->Qm; G = nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch; + LOG_D(PHY, "PUSCH nb_rb %d Q_m %d ulsch_harq->Nsymb_pusch %d\n",nb_rb, Q_m, ulsch_harq->Nsymb_pusch); //#ifdef DEBUG_ULSCH_DECODING - LOG_D(PHY,"[PUSCH %d] Frame %d, Subframe %d: ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): A %d, round %d, RV %d, O_r1 %d, O_RI %d, O_ACK %d, G %d, Q_m %d Nsymb_pusch %d nb_rb %d\n", + LOG_D(PHY,"[PUSCH harq %d] Frame %d, Subframe %d: ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): TBS %d, round %d, RV %d, O_r1 %d, O_RI %d, O_ACK %d, G %d, Q_m %d Nsymb_pusch %d nb_rb %d\n", harq_pid, proc->frame_rx,subframe, frame_parms->Nid_cell,ulsch->rnti,x2, @@ -833,6 +506,12 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, subframe); // Compute Q_ri Qprime = ulsch_harq->O_RI*ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_ri_times8; + LOG_D(PHY, "Qprime %d, O_RI %d, Msc %d, Nym %d beta %d\n", + Qprime, + ulsch_harq->O_RI, + ulsch_harq->Msc_initial, + ulsch_harq->Nsymb_initial, + ulsch->beta_offset_ri_times8); if (Qprime > 0 ) { if ((Qprime % (8*sumKr)) > 0) @@ -893,7 +572,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, G = G - Q_RI - Q_CQI; ulsch_harq->G = G; AssertFatal((int)G > 0, - "FATAL: ulsch_decoding.c G < 0 (%d) : Q_RI %d, Q_CQI %d\n",G,Q_RI,Q_CQI); + "FATAL: ulsch_decoding.c G < 0 (%u) : Q_RI %u, Q_CQI %u\n",G,Q_RI,Q_CQI); H = G + Q_CQI; Hprime = H/Q_m; // Demultiplexing/Deinterleaving of PUSCH/ACK/RI/CQI @@ -1209,8 +888,8 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, j2+=2; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; } break; @@ -1222,10 +901,10 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, j2+=4; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; } break; @@ -1237,12 +916,12 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, j2+=6; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; } break; @@ -1280,7 +959,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, */ int16_t *yp,*ep; - for (iprime=0,yp=&y[j2],ep=&ulsch_harq->e[0]; + for (iprime=0,yp=&y[j2],ep=&ulsch_harq->eUL[0]; iprimeO_ACK,ulsch_harq->o_ACK[0],ulsch_harq->o_ACK[1],ulsch_harq->o_ACK[2],ulsch_harq->o_ACK[3]); // Do ULSCH Decoding for data portion - ret = ulsch_decoding_data_all(eNB,UE_id,harq_pid,llr8_flag); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0); + ret = ulsch_decoding_data_all(eNB,proc, UE_id,harq_pid,llr8_flag); return(ret); } diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 1b0d7feaf5..f357e385f0 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -154,9 +154,9 @@ void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH) { switch (Msc_PUSCH) { case 12: - dft12((int16_t *)idft_in0,(int16_t *)idft_out0); - dft12((int16_t *)idft_in1,(int16_t *)idft_out1); - dft12((int16_t *)idft_in2,(int16_t *)idft_out2); + dft(DFT_12,(int16_t *)idft_in0,(int16_t *)idft_out0,0); + dft(DFT_12,(int16_t *)idft_in1,(int16_t *)idft_out1,0); + dft(DFT_12,(int16_t *)idft_in2,(int16_t *)idft_out2,0); #if defined(__x86_64__)||defined(__i386__) norm128 = _mm_set1_epi16(9459); #elif defined(__arm__) @@ -178,201 +178,201 @@ void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH) { break; case 24: - dft24(idft_in0,idft_out0,1); - dft24(idft_in1,idft_out1,1); - dft24(idft_in2,idft_out2,1); + dft(DFT_24,idft_in0,idft_out0,1); + dft(DFT_24,idft_in1,idft_out1,1); + dft(DFT_24,idft_in2,idft_out2,1); break; case 36: - dft36(idft_in0,idft_out0,1); - dft36(idft_in1,idft_out1,1); - dft36(idft_in2,idft_out2,1); + dft(DFT_36,idft_in0,idft_out0,1); + dft(DFT_36,idft_in1,idft_out1,1); + dft(DFT_36,idft_in2,idft_out2,1); break; case 48: - dft48(idft_in0,idft_out0,1); - dft48(idft_in1,idft_out1,1); - dft48(idft_in2,idft_out2,1); + dft(DFT_48,idft_in0,idft_out0,1); + dft(DFT_48,idft_in1,idft_out1,1); + dft(DFT_48,idft_in2,idft_out2,1); break; case 60: - dft60(idft_in0,idft_out0,1); - dft60(idft_in1,idft_out1,1); - dft60(idft_in2,idft_out2,1); + dft(DFT_60,idft_in0,idft_out0,1); + dft(DFT_60,idft_in1,idft_out1,1); + dft(DFT_60,idft_in2,idft_out2,1); break; case 72: - dft72(idft_in0,idft_out0,1); - dft72(idft_in1,idft_out1,1); - dft72(idft_in2,idft_out2,1); + dft(DFT_72,idft_in0,idft_out0,1); + dft(DFT_72,idft_in1,idft_out1,1); + dft(DFT_72,idft_in2,idft_out2,1); break; case 96: - dft96(idft_in0,idft_out0,1); - dft96(idft_in1,idft_out1,1); - dft96(idft_in2,idft_out2,1); + dft(DFT_96,idft_in0,idft_out0,1); + dft(DFT_96,idft_in1,idft_out1,1); + dft(DFT_96,idft_in2,idft_out2,1); break; case 108: - dft108(idft_in0,idft_out0,1); - dft108(idft_in1,idft_out1,1); - dft108(idft_in2,idft_out2,1); + dft(DFT_108,idft_in0,idft_out0,1); + dft(DFT_108,idft_in1,idft_out1,1); + dft(DFT_108,idft_in2,idft_out2,1); break; case 120: - dft120(idft_in0,idft_out0,1); - dft120(idft_in1,idft_out1,1); - dft120(idft_in2,idft_out2,1); + dft(DFT_120,idft_in0,idft_out0,1); + dft(DFT_120,idft_in1,idft_out1,1); + dft(DFT_120,idft_in2,idft_out2,1); break; case 144: - dft144(idft_in0,idft_out0,1); - dft144(idft_in1,idft_out1,1); - dft144(idft_in2,idft_out2,1); + dft(DFT_144,idft_in0,idft_out0,1); + dft(DFT_144,idft_in1,idft_out1,1); + dft(DFT_144,idft_in2,idft_out2,1); break; case 180: - dft180(idft_in0,idft_out0,1); - dft180(idft_in1,idft_out1,1); - dft180(idft_in2,idft_out2,1); + dft(DFT_180,idft_in0,idft_out0,1); + dft(DFT_180,idft_in1,idft_out1,1); + dft(DFT_180,idft_in2,idft_out2,1); break; case 192: - dft192(idft_in0,idft_out0,1); - dft192(idft_in1,idft_out1,1); - dft192(idft_in2,idft_out2,1); + dft(DFT_192,idft_in0,idft_out0,1); + dft(DFT_192,idft_in1,idft_out1,1); + dft(DFT_192,idft_in2,idft_out2,1); break; case 216: - dft216(idft_in0,idft_out0,1); - dft216(idft_in1,idft_out1,1); - dft216(idft_in2,idft_out2,1); + dft(DFT_216,idft_in0,idft_out0,1); + dft(DFT_216,idft_in1,idft_out1,1); + dft(DFT_216,idft_in2,idft_out2,1); break; case 240: - dft240(idft_in0,idft_out0,1); - dft240(idft_in1,idft_out1,1); - dft240(idft_in2,idft_out2,1); + dft(DFT_240,idft_in0,idft_out0,1); + dft(DFT_240,idft_in1,idft_out1,1); + dft(DFT_240,idft_in2,idft_out2,1); break; case 288: - dft288(idft_in0,idft_out0,1); - dft288(idft_in1,idft_out1,1); - dft288(idft_in2,idft_out2,1); + dft(DFT_288,idft_in0,idft_out0,1); + dft(DFT_288,idft_in1,idft_out1,1); + dft(DFT_288,idft_in2,idft_out2,1); break; case 300: - dft300(idft_in0,idft_out0,1); - dft300(idft_in1,idft_out1,1); - dft300(idft_in2,idft_out2,1); + dft(DFT_300,idft_in0,idft_out0,1); + dft(DFT_300,idft_in1,idft_out1,1); + dft(DFT_300,idft_in2,idft_out2,1); break; case 324: - dft324((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft324((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft324((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_324,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_324,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_324,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 360: - dft360((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft360((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft360((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_360,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_360,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_360,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 384: - dft384((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft384((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft384((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_384,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_384,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_384,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 432: - dft432((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft432((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft432((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_432,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_432,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_432,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 480: - dft480((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft480((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft480((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_480,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_480,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_480,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 540: - dft540((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft540((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft540((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_540,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_540,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_540,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 576: - dft576((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft576((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft576((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_576,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_576,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_576,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 600: - dft600((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft600((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft600((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_600,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_600,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_600,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 648: - dft648((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft648((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft648((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_648,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_648,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_648,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 720: - dft720((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft720((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft720((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_720,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_720,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_720,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 768: - dft768((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft768((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft768((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_768,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_768,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_768,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 864: - dft864((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft864((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft864((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_864,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_864,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_864,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 900: - dft900((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft900((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft900((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_900,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_900,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_900,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 960: - dft960((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft960((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft960((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_960,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_960,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_960,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 972: - dft972((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft972((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft972((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_972,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_972,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_972,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 1080: - dft1080((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft1080((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft1080((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_1080,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_1080,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_1080,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 1152: - dft1152((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft1152((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft1152((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_1152,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_1152,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_1152,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 1200: - dft1200(idft_in0,idft_out0,1); - dft1200(idft_in1,idft_out1,1); - dft1200(idft_in2,idft_out2,1); + dft(DFT_1200,idft_in0,idft_out0,1); + dft(DFT_1200,idft_in1,idft_out1,1); + dft(DFT_1200,idft_in2,idft_out2,1); break; default: @@ -780,7 +780,6 @@ void ulsch_channel_compensation(int32_t **rxdataF_ext, #endif for (rb=0; rbharq_processes[harq_pid]->RTC[r], G, //G dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, + dlsch->harq_processes[harq_pid]->eDL+r_offset, dlsch->harq_processes[harq_pid]->C, // C dlsch->Nsoft, // Nsoft, dlsch->Mdlharq, diff --git a/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c index afa46de820..ba904629a1 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c @@ -38,7 +38,6 @@ #include "PHY/MODULATION/modulation_UE.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/LTE_REFSIG/lte_refsig.h" -#include "openair2/LAYER2/MAC/mac_proto.h" #include "common_lib.h" #include "PHY/INIT/phy_init.h" diff --git a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c index 49fa484c26..e4083863f0 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c @@ -65,7 +65,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 uint16_t *prach_root_sequence_map; uint16_t preamble_offset,preamble_shift; uint16_t preamble_index0,n_shift_ra,n_shift_ra_bar; - uint16_t d_start,numshift; + uint16_t d_start=-1,numshift; uint8_t prach_fmt = get_prach_fmt(prach_ConfigIndex,frame_type); //uint8_t Nsp=2; //uint8_t f_ra,t1_ra; @@ -338,11 +338,11 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 switch (ue->frame_parms.N_RB_UL) { case 6: if (prach_fmt == 4) { - idft256(prachF,prach2,1); + idft(IDFT_256,prachF,prach2,1); memmove( prach, prach+512, Ncp<<2 ); prach_len = 256+Ncp; } else { - idft1536(prachF,prach2,1); + idft(IDFT_1536,prachF,prach2,1); memmove( prach, prach+3072, Ncp<<2 ); prach_len = 1536+Ncp; @@ -356,12 +356,12 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 case 15: if (prach_fmt == 4) { - idft512(prachF,prach2,1); + idft(IDFT_512,prachF,prach2,1); //TODO: account for repeated format in dft output memmove( prach, prach+1024, Ncp<<2 ); prach_len = 512+Ncp; } else { - idft3072(prachF,prach2,1); + idft(IDFT_3072,prachF,prach2,1); memmove( prach, prach+6144, Ncp<<2 ); prach_len = 3072+Ncp; @@ -376,11 +376,11 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 case 25: default: if (prach_fmt == 4) { - idft1024(prachF,prach2,1); + idft(IDFT_1024,prachF,prach2,1); memmove( prach, prach+2048, Ncp<<2 ); prach_len = 1024+Ncp; } else { - idft6144(prachF,prach2,1); + idft(IDFT_6144,prachF,prach2,1); /*for (i=0;i<6144*2;i++) prach2[i]<<=1;*/ memmove( prach, prach+12288, Ncp<<2 ); @@ -396,11 +396,11 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 case 50: if (prach_fmt == 4) { - idft2048(prachF,prach2,1); + idft(IDFT_2048,prachF,prach2,1); memmove( prach, prach+4096, Ncp<<2 ); prach_len = 2048+Ncp; } else { - idft12288(prachF,prach2,1); + idft(IDFT_12288,prachF,prach2,1); memmove( prach, prach+24576, Ncp<<2 ); prach_len = 12288+Ncp; @@ -414,12 +414,12 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 case 75: if (prach_fmt == 4) { - idft3072(prachF,prach2,1); + idft(IDFT_3072,prachF,prach2,1); //TODO: account for repeated format in dft output memmove( prach, prach+6144, Ncp<<2 ); prach_len = 3072+Ncp; } else { - idft18432(prachF,prach2,1); + idft(IDFT_18432,prachF,prach2,1); memmove( prach, prach+36864, Ncp<<2 ); prach_len = 18432+Ncp; @@ -434,11 +434,11 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 case 100: if (ue->frame_parms.threequarter_fs == 0) { if (prach_fmt == 4) { - idft4096(prachF,prach2,1); + idft(IDFT_4096,prachF,prach2,1); memmove( prach, prach+8192, Ncp<<2 ); prach_len = 4096+Ncp; } else { - idft24576(prachF,prach2,1); + idft(IDFT_24576,prachF,prach2,1); memmove( prach, prach+49152, Ncp<<2 ); prach_len = 24576+Ncp; @@ -449,12 +449,12 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 } } else { if (prach_fmt == 4) { - idft3072(prachF,prach2,1); + idft(IDFT_3072,prachF,prach2,1); //TODO: account for repeated format in dft output memmove( prach, prach+6144, Ncp<<2 ); prach_len = 3072+Ncp; } else { - idft18432(prachF,prach2,1); + idft(IDFT_18432,prachF,prach2,1); memmove( prach, prach+36864, Ncp<<2 ); prach_len = 18432+Ncp; printf("Generated prach for 100 PRB, 3/4 sampling\n"); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c index cc1f762e70..de1c3891da 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c @@ -446,6 +446,13 @@ uint32_t ulsch_encoding(uint8_t *a, Qprime = (ulsch->O + L) * ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_cqi_times8; else Qprime = 0; + LOG_D(PHY,"Qprime %d, O_RI %d + %d, Msc %d, Nym %d beta %d\n", + Qprime, + ulsch->O, L, + ulsch->harq_processes[harq_pid]->Msc_initial, + ulsch->harq_processes[harq_pid]->Nsymb_initial, + ulsch->beta_offset_cqi_times8); + if (Qprime > 0) { if ((Qprime % (8*sumKr)) > 0) @@ -455,7 +462,7 @@ uint32_t ulsch_encoding(uint8_t *a, } G = ulsch->harq_processes[harq_pid]->nb_rb * (12 * Q_m) * (ulsch->Nsymb_pusch); - + LOG_D(PHY,"G: rb %d * ( 12 * Qm %d ) * nsymb %d, Qprime %d, O_RI %d\n", ulsch->harq_processes[harq_pid]->nb_rb, Q_m, ulsch->Nsymb_pusch, Qprime, ulsch->O_RI); if (Qprime > (G - ulsch->O_RI)) Qprime = G - ulsch->O_RI; @@ -465,6 +472,7 @@ uint32_t ulsch_encoding(uint8_t *a, G = G - Q_RI - Q_CQI; + LOG_D(PHY,"new G: %d, Q_RI %d Q_CQI %d\n", G , Q_RI , Q_CQI); ulsch->harq_processes[harq_pid]->G = G; /* diff --git a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_modulation.c b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_modulation.c index a9878b4eae..b08fe30248 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_modulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_modulation.c @@ -104,9 +104,9 @@ void dft_lte(int32_t *z,int32_t *d, int32_t Msc_PUSCH, uint8_t Nsymb) switch (Msc_PUSCH) { case 12: - dft12((int16_t *)dft_in0,(int16_t *)dft_out0); - dft12((int16_t *)dft_in1,(int16_t *)dft_out1); - dft12((int16_t *)dft_in2,(int16_t *)dft_out2); + dft(DFT_12,(int16_t *)dft_in0,(int16_t *)dft_out0,0); + dft(DFT_12,(int16_t *)dft_in1,(int16_t *)dft_out1,0); + dft(DFT_12,(int16_t *)dft_in2,(int16_t *)dft_out2,0); /* dft12f(&((__m128i *)dft_in0)[0],&((__m128i *)dft_in0)[1],&((__m128i *)dft_in0)[2],&((__m128i *)dft_in0)[3],&((__m128i *)dft_in0)[4],&((__m128i *)dft_in0)[5],&((__m128i *)dft_in0)[6],&((__m128i *)dft_in0)[7],&((__m128i *)dft_in0)[8],&((__m128i *)dft_in0)[9],&((__m128i *)dft_in0)[10],&((__m128i *)dft_in0)[11], @@ -138,201 +138,201 @@ void dft_lte(int32_t *z,int32_t *d, int32_t Msc_PUSCH, uint8_t Nsymb) break; case 24: - dft24((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft24((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft24((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_24,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_24,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_24,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 36: - dft36((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft36((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft36((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_36,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_36,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_36,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 48: - dft48((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft48((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft48((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_48,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_48,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_48,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 60: - dft60((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft60((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft60((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_60,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_60,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_60,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 72: - dft72((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft72((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft72((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_72,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_72,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_72,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 96: - dft96((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft96((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft96((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_96,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_96,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_96,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 108: - dft108((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft108((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft108((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_108,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_108,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_108,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 120: - dft120((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft120((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft120((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_120,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_120,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_120,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 144: - dft144((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft144((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft144((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_144,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_144,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_144,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 180: - dft180((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft180((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft180((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_180,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_180,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_180,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 192: - dft192((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft192((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft192((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_192,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_192,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_192,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 216: - dft216((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft216((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft216((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_216,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_216,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_216,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 240: - dft240((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft240((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft240((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_240,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_240,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_240,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 288: - dft288((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft288((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft288((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_288,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_288,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_288,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 300: - dft300((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft300((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft300((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_300,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_300,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_300,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 324: - dft324((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft324((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft324((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_324,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_324,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_324,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 360: - dft360((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft360((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft360((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_360,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_360,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_360,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 384: - dft384((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft384((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft384((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_384,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_384,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_384,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 432: - dft432((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft432((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft432((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_432,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_432,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_432,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 480: - dft480((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft480((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft480((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_480,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_480,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_480,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 540: - dft540((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft540((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft540((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_540,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_540,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_540,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 576: - dft576((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft576((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft576((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_576,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_576,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_576,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 600: - dft600((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft600((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft600((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_600,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_600,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_600,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 648: - dft648((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft648((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft648((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_648,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_648,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_648,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 720: - dft720((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft720((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft720((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_720,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_720,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_720,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 768: - dft768((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft768((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft768((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_768,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_768,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_768,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 864: - dft864((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft864((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft864((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_864,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_864,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_864,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 900: - dft900((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft900((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft900((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_900,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_900,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_900,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 960: - dft960((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft960((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft960((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_960,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_960,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_960,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 972: - dft972((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft972((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft972((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_972,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_972,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_972,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 1080: - dft1080((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft1080((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft1080((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_1080,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_1080,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_1080,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 1152: - dft1152((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft1152((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft1152((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_1152,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_1152,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_1152,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; case 1200: - dft1200((int16_t*)dft_in0,(int16_t*)dft_out0,1); - dft1200((int16_t*)dft_in1,(int16_t*)dft_out1,1); - dft1200((int16_t*)dft_in2,(int16_t*)dft_out2,1); + dft(DFT_1200,(int16_t*)dft_in0,(int16_t*)dft_out0,1); + dft(DFT_1200,(int16_t*)dft_in1,(int16_t*)dft_out1,1); + dft(DFT_1200,(int16_t*)dft_in2,(int16_t*)dft_out2,1); break; } diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 5c8fce3c38..b27b692e66 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -242,7 +242,7 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) switch (Msc_PUSCH) { case 12: - dft12((int16_t *)dft_in0, (int16_t *)dft_out0); + dft(DFT_12,(int16_t *)dft_in0, (int16_t *)dft_out0,0); #if defined(__x86_64__) || defined(__i386__) norm128 = _mm_set1_epi16(9459); @@ -260,135 +260,135 @@ void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH) break; case 24: - dft24((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_24,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 36: - dft36((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_36,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 48: - dft48((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_48,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 60: - dft60((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_60,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 72: - dft72((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_72,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 96: - dft96((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_96,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 108: - dft108((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_108,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 120: - dft120((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_120,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 144: - dft144((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_144,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 180: - dft180((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_180,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 192: - dft192((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_192,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 216: - dft216((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_216,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 240: - dft240((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_240,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 288: - dft288((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_288,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 300: - dft300((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_300,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 324: - dft324((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_324,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 360: - dft360((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_360,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 384: - dft384((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_384,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 432: - dft432((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_432,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 480: - dft480((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_480,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 540: - dft540((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_540,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 576: - dft576((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_576,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 600: - dft600((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_600,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 648: - dft648((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_648,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 720: - dft720((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_720,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 768: - dft768((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_768,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 864: - dft864((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_864,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 900: - dft900((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_900,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 960: - dft960((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_960,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 972: - dft972((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_960,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 1080: - dft1080((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_1080,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 1152: - dft1152((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_1152,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; case 1200: - dft1200((int16_t*)dft_in0, (int16_t*)dft_out0, 1); + dft(DFT_1200,(int16_t*)dft_in0, (int16_t*)dft_out0, 1); break; } diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index cbeeca1327..855e649cc5 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -95,41 +95,41 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input volatile int *output_ptr=(int*)0; int *temp_ptr=(int*)0; - void (*idft)(int16_t *,int16_t *, int); + idft_size_idx_t idftsize; switch (fftsize) { case 128: - idft = idft128; + idftsize = IDFT_128; break; case 256: - idft = idft256; + idftsize = IDFT_256; break; case 512: - idft = idft512; + idftsize = IDFT_512; break; case 1024: - idft = idft1024; + idftsize = IDFT_1024; break; case 1536: - idft = idft1536; + idftsize = IDFT_1536; break; case 2048: - idft = idft2048; + idftsize = IDFT_2048; break; case 3072: - idft = idft3072; + idftsize = IDFT_3072; break; case 4096: - idft = idft4096; + idftsize = IDFT_4096; break; default: - idft = idft512; + idftsize = IDFT_512; break; } @@ -148,12 +148,12 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input #ifndef __AVX2__ // handle 128-bit alignment for 128-bit SIMD (SSE4,NEON,AltiVEC) - idft((int16_t *)&input[i*fftsize], + idft(idftsize,(int16_t *)&input[i*fftsize], (fftsize==128) ? (int16_t *)temp : (int16_t *)&output[(i*fftsize) + ((1+i)*nb_prefix_samples)], 1); #else // on AVX2 need 256-bit alignment - idft((int16_t *)&input[i*fftsize], + idft(idftsize,(int16_t *)&input[i*fftsize], (int16_t *)temp, 1); diff --git a/openair1/PHY/MODULATION/slot_fep.c b/openair1/PHY/MODULATION/slot_fep.c index 163ebac65f..8f41735f10 100644 --- a/openair1/PHY/MODULATION/slot_fep.c +++ b/openair1/PHY/MODULATION/slot_fep.c @@ -49,36 +49,36 @@ int slot_fep(PHY_VARS_UE *ue, unsigned char harq_pid = dlsch_ue[0]->current_harq_pid; LTE_DL_UE_HARQ_t *dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; int uespec_pilot[9][1200];*/ - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsizeidx; int tmp_dft_in[2048] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; - break; - - case 256: - dft = dft256; - break; - - case 512: - dft = dft512; - break; - - case 1024: - dft = dft1024; - break; - - case 1536: - dft = dft1536; - break; - - case 2048: - dft = dft2048; + dftsizeidx = DFT_128; + break; + + case 256: + dftsizeidx = DFT_256; + break; + + case 512: + dftsizeidx = DFT_512; + break; + + case 1024: + dftsizeidx = DFT_1024; + break; + + case 1536: + dftsizeidx = DFT_1536; + break; + + case 2048: + dftsizeidx = DFT_2048; break; default: - dft = dft512; + dftsizeidx = DFT_512; break; } @@ -118,13 +118,13 @@ int slot_fep(PHY_VARS_UE *ue, memcpy((void *)tmp_dft_in, (void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsizeidx,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); #endif - dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); #if UE_TIMING_TRACE stop_meas(&ue->rx_dft_stats); @@ -153,10 +153,10 @@ int slot_fep(PHY_VARS_UE *ue, memcpy((void *)tmp_dft_in, (void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsizeidx,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly - dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } @@ -247,36 +247,36 @@ int front_end_fft(PHY_VARS_UE *ue, unsigned char harq_pid = dlsch_ue[0]->current_harq_pid; LTE_DL_UE_HARQ_t *dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; int uespec_pilot[9][1200];*/ - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsizeidx; int tmp_dft_in[2048] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; - break; - - case 256: - dft = dft256; - break; - - case 512: - dft = dft512; - break; - - case 1024: - dft = dft1024; - break; - - case 1536: - dft = dft1536; - break; - - case 2048: - dft = dft2048; - break; - - default: - dft = dft512; + dftsizeidx = DFT_128; + break; + + case 256: + dftsizeidx = DFT_256; + break; + + case 512: + dftsizeidx = DFT_512; + break; + + case 1024: + dftsizeidx = DFT_1024; + break; + + case 1536: + dftsizeidx = DFT_1536; + break; + + case 2048: + dftsizeidx = DFT_2048; + break; + + default: + dftsizeidx = DFT_512; break; } @@ -319,11 +319,11 @@ int front_end_fft(PHY_VARS_UE *ue, memcpy((void *)tmp_dft_in, (void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsizeidx,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly start_meas(&ue->rx_dft_stats); - dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); stop_meas(&ue->rx_dft_stats); } @@ -349,10 +349,10 @@ int front_end_fft(PHY_VARS_UE *ue, memcpy((void *)tmp_dft_in, (void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsizeidx,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly - dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[threadId].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } diff --git a/openair1/PHY/MODULATION/slot_fep_mbsfn.c b/openair1/PHY/MODULATION/slot_fep_mbsfn.c index 38d78119e3..6036745029 100644 --- a/openair1/PHY/MODULATION/slot_fep_mbsfn.c +++ b/openair1/PHY/MODULATION/slot_fep_mbsfn.c @@ -42,35 +42,35 @@ int slot_fep_mbsfn(PHY_VARS_UE *ue, unsigned int subframe_offset; // int i; unsigned int frame_length_samples = frame_parms->samples_per_tti * 10; - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsizeidx; switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; - break; - - case 256: - dft = dft256; - break; - - case 512: - dft = dft512; - break; - - case 1024: - dft = dft1024; - break; - - case 1536: - dft = dft1536; - break; - - case 2048: - dft = dft2048; - break; - - default: - dft = dft512; + dftsizeidx = DFT_128; + break; + + case 256: + dftsizeidx = DFT_256; + break; + + case 512: + dftsizeidx = DFT_512; + break; + + case 1024: + dftsizeidx = DFT_1024; + break; + + case 1536: + dftsizeidx = DFT_1536; + break; + + case 2048: + dftsizeidx = DFT_2048; + break; + + default: + dftsizeidx = DFT_512; break; } @@ -110,7 +110,7 @@ int slot_fep_mbsfn(PHY_VARS_UE *ue, #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); #endif - dft((int16_t *)&common_vars->rxdata[aa][(sample_offset + + dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(sample_offset + nb_prefix_samples0 + subframe_offset - SOFFSET) % frame_length_samples], @@ -131,7 +131,7 @@ int slot_fep_mbsfn(PHY_VARS_UE *ue, #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); #endif - dft((int16_t *)&common_vars->rxdata[aa][(sample_offset + + dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(sample_offset + (frame_parms->ofdm_symbol_size+nb_prefix_samples0+nb_prefix_samples) + (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1) + subframe_offset- @@ -208,43 +208,43 @@ int slot_fep_mbsfn_khz_1dot25(PHY_VARS_UE *ue, int ofdm_symbol_size; unsigned int subframe_offset; unsigned int frame_length_samples = frame_parms->samples_per_tti * 10; - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsizeidx; AssertFatal(frame_parms->frame_type == FDD, "Frame is TDD!\n"); switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft1536; + dftsizeidx = DFT_1536; ofdm_symbol_size=1536; nb_prefix_samples=384; break; case 256: AssertFatal(1==0,"FeMBMS dft3072 not implemented\n"); - dft = dft3072; + dftsizeidx = DFT_3072; ofdm_symbol_size=3072; nb_prefix_samples=768; break; case 512: - dft = dft6144; + dftsizeidx = DFT_6144; nb_prefix_samples=1536; ofdm_symbol_size=6144; break; case 1024: - dft = dft12288; + dftsizeidx = DFT_12288; nb_prefix_samples=3072; ofdm_symbol_size=12288; break; case 1536: - dft = dft18432; + dftsizeidx = DFT_18432; nb_prefix_samples=4608; ofdm_symbol_size=18432; break; case 2048: - dft = dft24576; + dftsizeidx = DFT_24576; nb_prefix_samples=6144; ofdm_symbol_size=24576; break; @@ -265,7 +265,7 @@ int slot_fep_mbsfn_khz_1dot25(PHY_VARS_UE *ue, #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); #endif - dft((int16_t *)&common_vars->rxdata[aa][(sample_offset + + dft(dftsizeidx,(int16_t *)&common_vars->rxdata[aa][(sample_offset + nb_prefix_samples + subframe_offset - SOFFSET) % frame_length_samples], diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 5c704f3adf..7ff735cb71 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -62,44 +62,44 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, unsigned int rx_offset; - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; case 3072: - dft = dft3072; + dftsize = DFT_3072; break; case 4096: - dft = dft4096; + dftsize = DFT_4096; break; case 8192: - dft = dft8192; + dftsize = DFT_8192; break; default: @@ -155,14 +155,14 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, memcpy((void *)tmp_dft_in, (void *) &common_vars->rxdata[aa][rx_offset % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsize,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); #endif - dft((int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); #if UE_TIMING_TRACE stop_meas(&ue->rx_dft_stats); @@ -183,11 +183,11 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, memcpy((void *)tmp_dft_in, (void *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsize,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly - dft((int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } #if UE_TIMING_TRACE @@ -237,44 +237,44 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, unsigned int rx_offset; - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; case 3072: - dft = dft3072; + dftsize = DFT_3072; break; case 4096: - dft = dft4096; + dftsize = DFT_4096; break; case 8192: - dft = dft8192; + dftsize = DFT_8192; break; default: @@ -330,14 +330,15 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, memcpy((void *)tmp_dft_in, (void *) &common_vars->rxdata[aa][rx_offset], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsize,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); #endif - dft((int16_t *) &common_vars->rxdata[aa][rx_offset], + + dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); #if UE_TIMING_TRACE stop_meas(&ue->rx_dft_stats); @@ -358,11 +359,10 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, memcpy((void *)tmp_dft_in, (void *) &common_vars->rxdata[aa][rx_offset], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsize,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly - - dft((int16_t *) &common_vars->rxdata[aa][rx_offset], + dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } #if UE_TIMING_TRACE @@ -401,43 +401,43 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, int tmp_dft_in[8192] __attribute__ ((aligned (32))); - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; case 4096: - dft = dft4096; + dftsize = DFT_4096; break; case 8192: - dft = dft8192; + dftsize = DFT_8192; break; default: - dft = dft512; + dftsize = DFT_512; break; } @@ -457,12 +457,12 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, (void *) &rxdata[0], (frame_parms->ofdm_symbol_size-sample_offset+rxdata_offset)*sizeof(int)); - dft((int16_t *)&tmp_dft_in, + dft(dftsize,(int16_t *)&tmp_dft_in, (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); } else - dft((int16_t *)&rxdata[rxdata_offset-sample_offset], - (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); + dft(dftsize,(int16_t *)&rxdata[rxdata_offset-sample_offset], + (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); // clear DC carrier from OFDM symbols rxdataF[symbol * frame_parms->ofdm_symbol_size] = 0; diff --git a/openair1/PHY/MODULATION/slot_fep_ul.c b/openair1/PHY/MODULATION/slot_fep_ul.c index 3ac8537c69..746f8dbc0e 100644 --- a/openair1/PHY/MODULATION/slot_fep_ul.c +++ b/openair1/PHY/MODULATION/slot_fep_ul.c @@ -44,7 +44,7 @@ int slot_fep_ul(RU_t *ru, unsigned int slot_offset; - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; int tmp_dft_in[2048] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs unsigned int frame_length_samples = fp->samples_per_tti * 10; @@ -52,31 +52,31 @@ int slot_fep_ul(RU_t *ru, switch (fp->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; default: - dft = dft512; + dftsize = DFT_512; break; } @@ -109,7 +109,7 @@ int slot_fep_ul(RU_t *ru, LOG_D(PHY,"slot_fep: symbol 0 %d dB\n", dB_fixed(signal_energy(&common->rxdata_7_5kHz[aa][rx_offset],fp->ofdm_symbol_size))); #endif - dft( (int16_t *)&common->rxdata_7_5kHz[aa][rx_offset], + dft( dftsize,(int16_t *)&common->rxdata_7_5kHz[aa][rx_offset], (int16_t *)&common->rxdataF[aa][fp->ofdm_symbol_size*symbol], 1 ); @@ -121,13 +121,13 @@ int slot_fep_ul(RU_t *ru, memcpy((void *)&tmp_dft_in, (void *)&common->rxdata_7_5kHz[aa][(rx_offset % frame_length_samples)], fp->ofdm_symbol_size*sizeof(int)); - dft( (short *) tmp_dft_in, + dft( dftsize,(short *) tmp_dft_in, (short*) &common->rxdataF[aa][fp->ofdm_symbol_size*symbol], 1 ); } else{ - dft( (short *)&common->rxdata_7_5kHz[aa][rx_offset], + dft( dftsize,(short *)&common->rxdata_7_5kHz[aa][rx_offset], (short*)&common->rxdataF[aa][fp->ofdm_symbol_size*symbol], 1 ); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index a141970840..c515fe1263 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -439,55 +439,55 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, switch (gNB->frame_parms.ofdm_symbol_size) { case 128: - idft128((int16_t*) &ul_ch_estimates[aarx][symbol_offset], + idft(IDFT_128,(int16_t*) &ul_ch_estimates[aarx][symbol_offset], (int16_t*) ul_ch_estimates_time[aarx], 1); break; case 256: - idft256((int16_t*) &ul_ch_estimates[aarx][symbol_offset], + idft(IDFT_256,(int16_t*) &ul_ch_estimates[aarx][symbol_offset], (int16_t*) ul_ch_estimates_time[aarx], 1); break; case 512: - idft512((int16_t*) &ul_ch_estimates[aarx][symbol_offset], + idft(IDFT_512,(int16_t*) &ul_ch_estimates[aarx][symbol_offset], (int16_t*) ul_ch_estimates_time[aarx], 1); break; case 1024: - idft1024((int16_t*) &ul_ch_estimates[aarx][symbol_offset], + idft(IDFT_1024,(int16_t*) &ul_ch_estimates[aarx][symbol_offset], (int16_t*) ul_ch_estimates_time[aarx], 1); break; case 1536: - idft1536((int16_t*) &ul_ch_estimates[aarx][symbol_offset], + idft(IDFT_1536,(int16_t*) &ul_ch_estimates[aarx][symbol_offset], (int16_t*) ul_ch_estimates_time[aarx], 1); break; case 2048: - idft2048((int16_t*) &ul_ch_estimates[aarx][symbol_offset], + idft(IDFT_2048,(int16_t*) &ul_ch_estimates[aarx][symbol_offset], (int16_t*) ul_ch_estimates_time[aarx], 1); break; case 4096: - idft4096((int16_t*) &ul_ch_estimates[aarx][symbol_offset], + idft(IDFT_4096,(int16_t*) &ul_ch_estimates[aarx][symbol_offset], (int16_t*) ul_ch_estimates_time[aarx], 1); break; case 8192: - idft8192((int16_t*) &ul_ch_estimates[aarx][symbol_offset], + idft(IDFT_8192,(int16_t*) &ul_ch_estimates[aarx][symbol_offset], (int16_t*) ul_ch_estimates_time[aarx], 1); break; default: - idft512((int16_t*) &ul_ch_estimates[aarx][symbol_offset], + idft(IDFT_512,(int16_t*) &ul_ch_estimates[aarx][symbol_offset], (int16_t*) ul_ch_estimates_time[aarx], 1); break; diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index 9934b2163e..1bf2ef4fb2 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -26,7 +26,7 @@ #include "PHY/defs_gNB.h" #include "PHY/LTE_REFSIG/lte_refsig.h" - +#include "PHY/sse_intrin.h" /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS. @param PHY_VARS_gNB* gNB structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables @@ -50,4 +50,10 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB, unsigned short nb_pusch_rb, uint32_t re_offset, uint8_t dmrs_type); + +void init_scrambling_luts(void); + +extern __m64 byte2m64_re[256]; +extern __m64 byte2m64_im[256]; + #endif diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index a2e66d4e11..19b9736bcb 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -127,8 +127,8 @@ time_stats_t generic_time[TIME_LAST]; /************** FUNCTION ******************************************/ -void *get_idft(int ofdm_symbol_size); -void *get_dft(int ofdm_symbol_size); +idft_size_idx_t get_idft(int ofdm_symbol_size); +dft_size_idx_t get_dft(int ofdm_symbol_size); void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue); void free_context_synchro_nr(void); void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue); diff --git a/openair1/PHY/NR_REFSIG/scrambling_luts.c b/openair1/PHY/NR_REFSIG/scrambling_luts.c new file mode 100644 index 0000000000..eae54f94fb --- /dev/null +++ b/openair1/PHY/NR_REFSIG/scrambling_luts.c @@ -0,0 +1,62 @@ +/* + * 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 + */ + +/* Lookup tables for 3GPP scrambling/unscrambling */ + +/* Author R. Knopp / EURECOM / OpenAirInterface.org */ +#ifndef __SCRAMBLING_LUTS__C__ +#define __SCRAMBLING_LUTS__C__ + +#include "PHY/impl_defs_nr.h" +#include "PHY/sse_intrin.h" + +__m64 byte2m64_re[256]; +__m64 byte2m64_im[256]; + +void init_byte2m64() { + + for (int s=0;s<256;s++) { + byte2m64_re[s] = _mm_insert_pi16(byte2m64_re[s],(1-2*(s&1)),0); + byte2m64_im[s] = _mm_insert_pi16(byte2m64_im[s],(1-2*((s>>1)&1)),0); + byte2m64_re[s] = _mm_insert_pi16(byte2m64_re[s],(1-2*((s>>2)&1)),1); + byte2m64_im[s] = _mm_insert_pi16(byte2m64_im[s],(1-2*((s>>3)&1)),1); + byte2m64_re[s] = _mm_insert_pi16(byte2m64_re[s],(1-2*((s>>4)&1)),2); + byte2m64_im[s] = _mm_insert_pi16(byte2m64_im[s],(1-2*((s>>5)&1)),2); + byte2m64_re[s] = _mm_insert_pi16(byte2m64_re[s],(1-2*((s>>6)&1)),3); + byte2m64_im[s] = _mm_insert_pi16(byte2m64_im[s],(1-2*((s>>7)&1)),3); + printf("init_scrambling_luts: s %x (%d) ((%d,%d),(%d,%d),(%d,%d),(%d,%d))\n", + ((uint16_t*)&s)[0], + (1-2*(s&1)), + ((int16_t*)&byte2m64_re[s])[0],((int16_t*)&byte2m64_im[s])[0], + ((int16_t*)&byte2m64_re[s])[1],((int16_t*)&byte2m64_im[s])[1], + ((int16_t*)&byte2m64_re[s])[2],((int16_t*)&byte2m64_im[s])[2], + ((int16_t*)&byte2m64_re[s])[3],((int16_t*)&byte2m64_im[s])[3]); + + } +} + +void init_scrambling_luts() { + + init_byte2m64(); + +} + +#endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index c0fe5e8f3a..ec5aee3c8a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -137,7 +137,7 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { int N_reg = n_rb * pdcch_pdu_rel15->DurationSymbols; - int C; + int C=-1; for (int d=0;dnumDlDci;d++) { int L = pdcch_pdu_rel15->dci_pdu.AggregationLevel[d]; @@ -210,8 +210,7 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, for (int i=0;inumDlDci;i++) { - uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; - + //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->dci_pdu.RNTI[i],gNB,SEARCH_EXIST_OR_FREE); if( (dlsch_id<0) || (dlsch_id>=NUMBER_OF_NR_DLSCH_MAX) ){ @@ -248,7 +247,7 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB, for (int i=0;inumDlDci;i++) { - uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; + //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->dci_pdu.Payload[i]; // if there's no DL DCI then generate CCE list if (gNB->pdcch_pdu) nr_fill_cce_list(gNB,0); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 5e10e1dd06..adb040ec74 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -64,7 +64,6 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB) a_segments = a_segments/273; } - uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment #ifdef DEBUG_DLSCH_FREE @@ -82,7 +81,7 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB) #endif if (dlsch->harq_processes[i]->b) { - free16(dlsch->harq_processes[i]->b,dlsch_bytes); + free16(dlsch->harq_processes[i]->b,a_segments*1056); dlsch->harq_processes[i]->b = NULL; #ifdef DEBUG_DLSCH_FREE LOG_D(PHY,"Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b); diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 2f0ea46ecd..e317f71fbc 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -282,20 +282,20 @@ void rx_nr_prach_ru(RU_t *ru, if (prach_sequence_length == 0) { if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { dftlen=49152; - dft49152(prach2,rxsigF[aa],1); + dft(DFT_49152,prach2,rxsigF[aa],1); } if (prachFormat == 1 || prachFormat == 2) { - dft49152(prach2+98304,rxsigF[aa]+98304,1); + dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1); reps++; } if (prachFormat == 2) { - dft49152(prach2+(98304*2),rxsigF[aa]+(98304*2),1); - dft49152(prach2+(98304*3),rxsigF[aa]+(98304*3),1); + dft(DFT_49152,prach2+(98304*2),rxsigF[aa]+(98304*2),1); + dft(DFT_49152,prach2+(98304*3),rxsigF[aa]+(98304*3),1); reps+=2; } if (prachFormat == 3) { dftlen=12288; - for (int i=0;i<4;i++) dft12288(prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1); + for (int i=0;i<4;i++) dft(DFT_12288,prach2+(i*12288*2),rxsigF[aa]+(i*12288*2),1); reps=4; } }// 839 sequence @@ -307,23 +307,23 @@ void rx_nr_prach_ru(RU_t *ru, if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); else if (mu==1) { dftlen=2048; - dft2048(prach2,rxsigF[aa],1); + dft(DFT_2048,prach2,rxsigF[aa],1); if (prachFormat != 7) { // !=C0 - dft2048(prach2+4096,rxsigF[aa]+4096,1); + dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1); reps++; } if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { - dft2048(prach2+4096*2,rxsigF[aa]+4096*2,1); - dft2048(prach2+4096*3,rxsigF[aa]+4096*3,1); + 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 == 2 || prachFormat == 5 || prachFormat == 6) { - dft2048(prach2+4096*4,rxsigF[aa]+4096*4,1); - dft2048(prach2+4096*5,rxsigF[aa]+4096*5,1); + 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 == 6) { - for (int i=6;i<12;i++) dft2048(prach2+(4096*i),rxsigF[aa]+(4096*i),1); + for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1); reps+=6; } } @@ -338,21 +338,21 @@ void rx_nr_prach_ru(RU_t *ru, AssertFatal(fp->N_RB_UL <= 107,"cannot do 108..136 PRBs with 3/4 sampling\n"); if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { dftlen=36864; - dft36864(prach2,rxsigF[aa],1); + dft(DFT_36864,prach2,rxsigF[aa],1); reps++; } if (prachFormat == 1 || prachFormat == 2) { - dft36864(prach2+73728,rxsigF[aa]+73728,1); + dft(DFT_36864,prach2+73728,rxsigF[aa]+73728,1); reps++; } if (prachFormat == 2) { - dft36864(prach2+(73728*2),rxsigF[aa]+(73728*2),1); - dft36864(prach2+(73728*3),rxsigF[aa]+(73728*3),1); + dft(DFT_36864,prach2+(73728*2),rxsigF[aa]+(73728*2),1); + dft(DFT_36864,prach2+(73728*3),rxsigF[aa]+(73728*3),1); reps+=2; } if (prachFormat == 3) { dftlen=9216; - for (int i=0;i<4;i++) dft9216(prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1); + for (int i=0;i<4;i++) dft(DFT_9216,prach2+(i*9216*2),rxsigF[aa]+(i*9216*2),1); reps=4; } } else { @@ -362,24 +362,24 @@ void rx_nr_prach_ru(RU_t *ru, if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); else if (mu==1) { dftlen=1536; - dft1536(prach2,rxsigF[aa],1); + dft(DFT_1536,prach2,rxsigF[aa],1); if (prachFormat != 7) { - dft1536(prach2+3072,rxsigF[aa]+3072,1); + dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); reps++; } if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { - dft1536(prach2+3072*2,rxsigF[aa]+3072*2,1); - dft1536(prach2+3072*3,rxsigF[aa]+3072*3,1); + 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 == 2 || prachFormat == 5 || prachFormat == 6) { - dft1536(prach2+3072*4,rxsigF[aa]+3072*4,1); - dft1536(prach2+3072*5,rxsigF[aa]+3072*5,1); + 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 == 6) { - for (int i=6;i<12;i++) dft1536(prach2+(3072*i),rxsigF[aa]+(3072*i),1); + for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1); reps+=6; } }// mu==1 @@ -397,20 +397,20 @@ void rx_nr_prach_ru(RU_t *ru, if (prach_sequence_length == 0) { if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { dftlen=98304; - dft98304(prach2,rxsigF[aa],1); + dft(DFT_98304,prach2,rxsigF[aa],1); } if (prachFormat == 1 || prachFormat == 2) { - dft98304(prach2+196608,rxsigF[aa]+196608,1); + dft(DFT_98304,prach2+196608,rxsigF[aa]+196608,1); reps++; } if (prachFormat == 2) { - dft98304(prach2+196608*2,rxsigF[aa]+196608*2,1); - dft98304(prach2+(196608*3),rxsigF[aa]+(196608*3),1); + dft(DFT_98304,prach2+196608*2,rxsigF[aa]+196608*2,1); + dft(DFT_98304,prach2+(196608*3),rxsigF[aa]+(196608*3),1); reps+=2; } if (prachFormat == 3) { dftlen=24576; - for (int i=0;i<4;i++) dft24576(prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1); + for (int i=0;i<4;i++) dft(DFT_24576,prach2+(i*2*24576),rxsigF[aa]+(i*2*24576),1); reps=4; } } @@ -422,24 +422,24 @@ void rx_nr_prach_ru(RU_t *ru, if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); else if (mu==1) { dftlen=4096; - dft4096(prach2,rxsigF[aa],1); + dft(DFT_4096,prach2,rxsigF[aa],1); if (prachFormat != 7) { //!=C0 - dft4096(prach2+8192,rxsigF[aa]+8192,1); + dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1); reps++; } if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { - dft4096(prach2+8192*2,rxsigF[aa]+8192*2,1); - dft4096(prach2+8192*3,rxsigF[aa]+8192*3,1); + 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 == 2 || prachFormat == 5 || prachFormat == 6) { - dft4096(prach2+8192*4,rxsigF[aa]+8192*4,1); - dft4096(prach2+8192*5,rxsigF[aa]+8192*5,1); + 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 == 6) { - for (int i=6;i<12;i++) dft4096(prach2+(8192*i),rxsigF[aa]+(8192*i),1); + for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1); reps+=6; } } @@ -454,16 +454,16 @@ void rx_nr_prach_ru(RU_t *ru, if (prach_sequence_length == 0) { if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { dftlen=73728; - dft73728(prach2,rxsigF[aa],1); + dft(DFT_73728,prach2,rxsigF[aa],1); reps++; } if (prachFormat == 1 || prachFormat == 2) { - dft73728(prach2+(2*73728),rxsigF[aa]+(2*73728),1); + dft(DFT_73728,prach2+(2*73728),rxsigF[aa]+(2*73728),1); reps++; } if (prachFormat == 3) { dftlen=18432; - for (int i=0;i<4;i++) dft18432(prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1); + for (int i=0;i<4;i++) dft(DFT_18432,prach2+(i*2*18432),rxsigF[aa]+(i*2*18432),1); reps=4; } } else { @@ -474,24 +474,24 @@ void rx_nr_prach_ru(RU_t *ru, if (mu==0) AssertFatal(1==0,"Shouldn't get here\n"); else if (mu==1) { dftlen=3072; - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); if (prachFormat != 7) { //!=C0 - dft3072(prach2+6144,rxsigF[aa]+6144,1); + dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); reps++; } if (prachFormat == 1 || prachFormat == 2 || prachFormat == 4 || prachFormat == 5 || prachFormat == 6 || prachFormat == 8) { - dft3072(prach2+6144*2,rxsigF[aa]+6144*2,1); - dft3072(prach2+6144*3,rxsigF[aa]+6144*3,1); + 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 == 2 || prachFormat == 5 || prachFormat == 6) { - dft3072(prach2+6144*4,rxsigF[aa]+6144*4,1); - dft3072(prach2+6144*5,rxsigF[aa]+6144*5,1); + 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 == 6) { - for (int i=6;i<12;i++) dft3072(prach2+(6144*i),rxsigF[aa]+(6144*i),1); + for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1); reps+=6; } } @@ -738,12 +738,12 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) if (N_ZC == 839) { log2_ifft_size = 10; - idft1024(prachF,prach_ifft_tmp,1); + idft(IDFT_1024,prachF,prach_ifft_tmp,1); // compute energy and accumulate over receive antennas for (i=0;i<2048;i++) prach_ifft[i] += ((int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[i<<1] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)])>>10; } else { - idft256(prachF,prach_ifft_tmp,1); + idft(IDFT_256,prachF,prach_ifft_tmp,1); log2_ifft_size = 8; // compute energy and accumulate over receive antennas and repetitions for BR for (i=0;i<256;i++) diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport.h b/openair1/PHY/NR_TRANSPORT/nr_transport.h index eb5c9bb52a..d858019d18 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport.h @@ -111,6 +111,7 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint8_t abstraction_flag, uint16_t N_RB); + void nr_decode_pucch1(int32_t **rxdataF, pucch_GroupHopping_t pucch_GroupHopping, uint32_t n_id, // hoppingID higher layer parameter @@ -131,6 +132,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, nfapi_nr_pucch_pdu_t* pucch_pdu); + void rx_nr_prach(PHY_VARS_gNB *gNB, nfapi_nr_prach_pdu_t *prach_pdu, int frame, @@ -160,4 +162,5 @@ void init_prach_ru_list(RU_t *ru); void free_nr_ru_prach_entry(RU_t *ru, int prach_id); + #endif /*__NR_TRANSPORT__H__*/ diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto_common.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto_common.h index 78dd266eea..e695fc7884 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto_common.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto_common.h @@ -29,8 +29,8 @@ * \note * \warning */ -#ifndef __NR_TRANSPORT_PROTO_UE__H__ -#define __NR_TRANSPORT_PROTO_UE__H__ +#ifndef __NR_TRANSPORT_PROTO_COMMON_H__ +#define __NR_TRANSPORT_PROTO_COMMON_H__ #include "PHY/defs_nr_UE.h" #include "SCHED_NR_UE/defs.h" //#include "PHY/LTE_TRANSPORT/transport_common_proto.h" @@ -43,29 +43,6 @@ * @{ */ -/** \fn free_ue_dlsch(NR_UE_DLSCH_t *dlsch) - \brief This function frees memory allocated for a particular DLSCH at UE - @param dlsch Pointer to DLSCH to be removed -*/ -void free_nr_ue_dlsch(NR_UE_DLSCH_t *dlsch); - -/** \fn new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag) - \brief This function allocates structures for a particular DLSCH at UE - @returns Pointer to DLSCH to be removed - @param Kmimo Kmimo factor from 36-212/36-213 - @param Mdlharq Maximum number of HARQ rounds (36-212/36-213) - @param Nsoft Soft-LLR buffer size from UE-Category - @params N_RB_DL total number of resource blocks (determine the operating BW) - @param abstraction_flag Flag to indicate abstracted interface -*/ -NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag); - - -void free_nr_ue_ulsch(NR_UE_ULSCH_t *ulsch); - - -NR_UE_ULSCH_t *new_nr_ue_ulsch(unsigned char N_RB_UL, int number_of_harq_pids, uint8_t abstraction_flag); - void fill_UE_dlsch_MCH(PHY_VARS_NR_UE *ue,int mcs,int ndi,int rvidx,int eNB_id); int rx_pmch(PHY_VARS_NR_UE *phy_vars_ue, @@ -1055,21 +1032,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, NR_DL_FRAME_PARMS* frame_parms, uint8_t harq_pid); -/*! \brief Perform PUSCH scrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 - @param[in] in Pointer to input bits - @param[in] size of input bits - @param[in] Nid cell id - @param[in] n_RNTI CRNTI - @param[out] out the scrambled bits -*/ - -void nr_pusch_codeword_scrambling(uint8_t *in, - uint16_t size, - uint32_t Nid, - uint32_t n_RNTI, - uint32_t* out); - - uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, int eNB_id, @@ -1128,17 +1090,6 @@ int32_t nr_rx_pdsch(PHY_VARS_NR_UE *phy_vars_ue, uint8_t i_mod, uint8_t harq_pid); -int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, - uint32_t frame, - uint8_t nr_tti_rx, - uint8_t eNB_id, - MIMO_mode_t mimo_mode, - uint32_t high_speed_flag, - uint8_t is_secondary_ue, - int nb_coreset_active, - uint16_t symbol_mon, - NR_SEARCHSPACE_TYPE_t searchSpaceType); - /*! \brief Extract PSS and SSS resource elements @param phy_vars_ue Pointer to UE variables @param[out] pss_ext contain the PSS signals after the extraction @@ -1471,18 +1422,6 @@ void init_transport_channels(uint8_t); void generate_RIV_tables(void); -/*! - \brief This function performs the initial cell search procedure - PSS detection, SSS detection and PBCH detection. At the - end, the basic frame parameters are known (Frame configuration - TDD/FDD and cyclic prefix length, - N_RB_DL, PHICH_CONFIG and Nid_cell) and the UE can begin decoding PDCCH and DLSCH SI to retrieve the rest. Once these - parameters are know, the routine calls some basic initialization routines (cell-specific reference signals, etc.) - @param phy_vars_ue Pointer to UE variables - @param mode current running mode -*/ -int nr_initial_sync(UE_nr_rxtx_proc_t *proc, - PHY_VARS_NR_UE *phy_vars_ue, runmode_t mode); - - /*! \brief Encoding of PUSCH/ACK/RI/ACK from 36-212. @param a Pointer to ulsch SDU @@ -1727,10 +1666,6 @@ uint8_t get_prach_prb_offset(NR_DL_FRAME_PARMS *frame_parms, uint8_t n_ra_prboffset, uint8_t tdd_mapindex, uint16_t Nf); -void nr_pdcch_unscrambling(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx, - int16_t *z, uint32_t length, uint16_t pdcch_DMRS_scrambling_id, int do_common); - - uint32_t lte_gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset); int nr_rx_pdsch(PHY_VARS_NR_UE *ue, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index c74bc16754..31fedfa31a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -70,13 +70,12 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr,uint8_t N_RB_UL) a_segments = a_segments/273; } - uint16_t ulsch_bytes = a_segments*1056; // allocated bytes per segment for (i=0; iharq_processes[i]) { if (ulsch->harq_processes[i]->b) { - free16(ulsch->harq_processes[i]->b,ulsch_bytes); + free16(ulsch->harq_processes[i]->b,a_segments*1056); ulsch->harq_processes[i]->b = NULL; } for (r=0; r #include #include @@ -8,10 +39,12 @@ #include "PHY/impl_defs_nr.h" #include "PHY/defs_nr_common.h" -#include "PHY/defs_nr_UE.h" +#include "PHY/defs_gNB.h" +#include "PHY/sse_intrin.h" #include "PHY/NR_UE_TRANSPORT/pucch_nr.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_transport.h" +#include "PHY/NR_REFSIG/nr_refsig.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -236,7 +269,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, for (l=0; lnr_of_symbols; l++) { l2 = l+pucch_pdu->start_symbol_index; - re_offset = (12*pucch_pdu->prb_start) + frame_parms->first_carrier_offset; + re_offset = (12*pucch_pdu->prb_start) + (12*pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; if (re_offset>= frame_parms->ofdm_symbol_size) re_offset-=frame_parms->ofdm_symbol_size; @@ -866,3 +899,496 @@ void nr_decode_pucch1( int32_t **rxdataF, } } +__m256i pucch2_3bit[8*2]; +__m256i pucch2_4bit[16*2]; +__m256i pucch2_5bit[32*2]; +__m256i pucch2_6bit[64*2]; +__m256i pucch2_7bit[128*2]; +__m256i pucch2_8bit[256*2]; +__m256i pucch2_9bit[512*2]; +__m256i pucch2_10bit[1024*2]; +__m256i pucch2_11bit[2048*2]; + +__m256i *pucch2_lut[9]={pucch2_3bit, + pucch2_4bit, + pucch2_5bit, + pucch2_6bit, + pucch2_7bit, + pucch2_8bit, + pucch2_9bit, + pucch2_10bit, + pucch2_11bit}; + +void init_pucch2_luts() { + + uint32_t out; + int8_t bit; + + for (int b=3;b<12;b++) { + for (uint16_t i=0;i<(1< 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,0); + bit = (out&0x2) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,0); + bit = (out&0x4) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,1); + bit = (out&0x8) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,1); + bit = (out&0x10) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,2); + bit = (out&0x20) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,2); + bit = (out&0x40) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,3); + bit = (out&0x80) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,3); + bit = (out&0x100) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,4); + bit = (out&0x200) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,4); + bit = (out&0x400) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,5); + bit = (out&0x800) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,5); + bit = (out&0x1000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,6); + bit = (out&0x2000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,6); + bit = (out&0x4000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,7); + bit = (out&0x8000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,7); + bit = (out&0x10000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,8); + bit = (out&0x20000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,8); + bit = (out&0x40000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,9); + bit = (out&0x80000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,9); + bit = (out&0x100000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,10); + bit = (out&0x200000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,10); + bit = (out&0x400000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,11); + bit = (out&0x800000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,11); + bit = (out&0x1000000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,12); + bit = (out&0x2000000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,12); + bit = (out&0x4000000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,13); + bit = (out&0x8000000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,13); + bit = (out&0x10000000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,14); + bit = (out&0x20000000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,14); + bit = (out&0x40000000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,15); + bit = (out&0x80000000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,15); + } + } +} + + +void nr_decode_pucch2(PHY_VARS_gNB *gNB, + int slot, + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, + nfapi_nr_pucch_pdu_t* pucch_pdu) { + + int32_t **rxdataF = gNB->common_vars.rxdataF; + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); + + AssertFatal(pucch_pdu->nr_of_symbols==1 || pucch_pdu->nr_of_symbols==2, + "Illegal number of symbols for PUCCH 2 %d\n",pucch_pdu->nr_of_symbols); + + + //extract pucch and dmrs first + + int l2; + int re_offset = (12*pucch_pdu->prb_start) + (12*pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; + if (re_offset>= frame_parms->ofdm_symbol_size) + re_offset-=frame_parms->ofdm_symbol_size; + + AssertFatal(pucch_pdu->prb_size*pucch_pdu->nr_of_symbols > 1,"number of PRB*SYMB (%d,%d)< 2", + pucch_pdu->prb_size,pucch_pdu->nr_of_symbols); + + int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value; + int Prx2 = (Prx==1)?2:Prx; + // use 2 for Nb antennas in case of single antenna to allow the following allocations + int16_t r_re_ext[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t r_im_ext[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t r_re_ext2[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t r_im_ext2[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t rd_re_ext[Prx2][4*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t rd_im_ext[Prx2][4*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + + int16_t *rp[Prx2]; + __m64 dmrs_re,dmrs_im; + + for (int aa=0;aaofdm_symbol_size)+re_offset]); + +#ifdef DEBUG_NR_PUCCH_RX + printf("Decoding pucch2 for %d symbols, %d PRB\n",pucch_pdu->nr_of_symbols,pucch_pdu->prb_size); +#endif + + int nc_group_size=1; // 2 PRB + int ngroup = pucch_pdu->prb_size/nc_group_size/2; + int32_t corr32_re[ngroup][Prx2],corr32_im[ngroup][Prx2]; + for (int aa=0;aanr_of_symbols == 1) { + AssertFatal((pucch_pdu->prb_size&1) == 0,"prb_size %d is not a multiple of 2\n",pucch_pdu->prb_size); + // 24 PRBs contains 48x16-bit, so 6x8x16-bit + for (int prb=0;prbprb_size;prb+=2) { + for (int aa=0;aa (%d,%d)\n",aa,prb+(i>>2),i,rd_re_ext[aa][i],rd_im_ext[aa],i); +#endif + } // aa + } // prb + + + // first compute DMRS component + uint32_t x1, x2, s=0; + x2 = (((1<<17)*((14*slot) + (pucch_pdu->start_symbol_index) + 1)*((2*pucch_pdu->dmrs_scrambling_id) + 1)) + (2*pucch_pdu->dmrs_scrambling_id))%(1U<<31); // c_init calculation according to TS38.211 subclause +#ifdef DEBUG_NR_PUCCH_RX + printf("slot %d, start_symbol_index %d, dmrs_scrambling_id %d\n", + slot,pucch_pdu->start_symbol_index,pucch_pdu->dmrs_scrambling_id); +#endif + s = lte_gold_generic(&x1, &x2, 1); + + + for (int group=0;group>=5; + corr32_im[group][aa]>>=5; +#ifdef DEBUG_NR_PUCCH_RX + printf("Group %d: corr32 (%d,%d)\n",group,corr32_re[group][aa],corr32_im[group][aa]); +#endif + } //aa + + if ((group&3) == 3) s = lte_gold_generic(&x1, &x2, 0); + } // group + } + else { // 2 symbol case + AssertFatal(1==0, "Fill in 2 symbol PUCCH2 case\n"); + } + + uint32_t x1, x2, s=0; + // unscrambling + x2 = ((pucch_pdu->rnti)<<15)+pucch_pdu->data_scrambling_id; + s = lte_gold_generic(&x1, &x2, 1); +#ifdef DEBUG_NR_PUCCH_RX + printf("x2 %x, s %x\n",x2,s); +#endif + __m64 c_re0,c_im0,c_re1,c_im1,c_re2,c_im2,c_re3,c_im3; + re_offset=0; + for (int prb=0;prbprb_size;prb+=2,re_offset+=16) { + c_re0 = byte2m64_re[((uint8_t*)&s)[0]]; + c_im0 = byte2m64_im[((uint8_t*)&s)[0]]; + c_re1 = byte2m64_re[((uint8_t*)&s)[1]]; + c_im1 = byte2m64_im[((uint8_t*)&s)[1]]; + c_re2 = byte2m64_re[((uint8_t*)&s)[2]]; + c_im2 = byte2m64_im[((uint8_t*)&s)[2]]; + c_re3 = byte2m64_re[((uint8_t*)&s)[3]]; + c_im3 = byte2m64_im[((uint8_t*)&s)[3]]; + + for (int aa=0;aabit_len_csi_part1 + pucch_pdu->bit_len_csi_part2 == 0,"no csi for now\n"); + AssertFatal((pucch_pdu->bit_len_harq+pucch_pdu->sr_flag > 2 ) && (pucch_pdu->bit_len_harq+pucch_pdu->sr_flag < 12),"illegal length (%d,%d)\n",pucch_pdu->bit_len_harq,pucch_pdu->sr_flag); + int nb_bit = pucch_pdu->bit_len_harq+pucch_pdu->sr_flag; + __m256i *rp_re[Prx2]; + __m256i *rp2_re[Prx2]; + __m256i *rp_im[Prx2]; + __m256i *rp2_im[Prx2]; + for (int aa=0;aa>1], + ((int16_t*)&pucch2_lut[nb_bit-3][cw<<1])[1+(i>>1)]); + } + printf("\n"); +#endif + // do complex correlation + for (int aa=0;aa corr) { + corr = corr_tmp; + cw_ML=cw; + } + } + uint8_t corr_dB = dB_fixed64((uint64_t)corr); + LOG_D(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); + uci_pdu->harq.harq_bit_len = pucch_pdu->bit_len_harq; + + + int harq_bytes=pucch_pdu->bit_len_harq>>3; + if ((pucch_pdu->bit_len_harq&7) > 0) harq_bytes++; + uci_pdu->harq.harq_payload = (nfapi_nr_harq_t*)malloc(harq_bytes); + uci_pdu->harq.harq_crc = 2; + for (int i=0;iharq.harq_payload[i] = cw_ML & 255; + cw_ML>>=8; + } + + if (pucch_pdu->sr_flag == 1) { + uci_pdu->sr.sr_bit_len = 1; + uci_pdu->sr.sr_payload = malloc(1); + uci_pdu->sr.sr_payload[0] = cw_ML; + } +} + 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 24fcbf2e5b..d140442523 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -23,7 +23,6 @@ #include "PHY/defs_nr_UE.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "PHY/impl_defs_top.h" -//#include "openair2/LAYER2/MAC/mac_proto.h" #include "common/utils/LOG/vcd_signal_dumper.h" 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 be5c754beb..19564bd8d0 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -405,39 +405,39 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, } - void (*idft)(int16_t *,int16_t *, int); + idft_size_idx_t idftsizeidx; switch (ue->frame_parms.ofdm_symbol_size) { case 128: - idft = idft128; + idftsizeidx = IDFT_128; break; case 256: - idft = idft256; + idftsizeidx = IDFT_256; break; case 512: - idft = idft512; + idftsizeidx = IDFT_512; break; case 1024: - idft = idft1024; + idftsizeidx = IDFT_1024; break; case 1536: - idft = idft1536; + idftsizeidx = IDFT_1536; break; case 2048: - idft = idft2048; + idftsizeidx = IDFT_2048; break; case 3072: - idft = idft3072; + idftsizeidx = IDFT_3072; break; case 4096: - idft = idft4096; + idftsizeidx = IDFT_4096; break; default: @@ -453,7 +453,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, if (ue->pbch_vars[eNB_offset]->dl_ch_estimates[(p<<1)+aarx]) { LOG_D(PHY,"Channel Impulse Computation Slot %d ThreadId %d Symbol %d ch_offset %d\n", Ns, ue->current_thread_id[Ns], symbol, ch_offset); - idft((int16_t*) &ue->pbch_vars[eNB_offset]->dl_ch_estimates[(p<<1)+aarx][ch_offset], + idft(idftsizeidx, + (int16_t*) &ue->pbch_vars[eNB_offset]->dl_ch_estimates[(p<<1)+aarx][ch_offset], (int16_t*) ue->pbch_vars[eNB_offset]->dl_ch_estimates_time[(p<<1)+aarx],1); } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 6aa9ab9d4b..0dffb66c15 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -69,12 +69,11 @@ void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr,uint8_t N_RB_DL) a_segments = a_segments/273; } - uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment for (i=0; iMdlharq; i++) { if (dlsch->harq_processes[i]) { if (dlsch->harq_processes[i]->b) { - free16(dlsch->harq_processes[i]->b,dlsch_bytes); + free16(dlsch->harq_processes[i]->b,a_segments*1056); dlsch->harq_processes[i]->b = NULL; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index e7d930b34a..5c049f06c5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -41,6 +41,7 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "T.h" +#include #define NR_PRACH_DEBUG 1 @@ -78,6 +79,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ uint16_t rootSequenceIndex, prach_fmt_id, NCS, *prach_root_sequence_map, preamble_offset = 0; uint16_t preamble_shift = 0, preamble_index0, n_shift_ra, n_shift_ra_bar, d_start, numshift, N_ZC, u, offset, offset2, first_nonzero_root_idx; int16_t prach_tmp[98304*2*4] __attribute__((aligned(32))); + int16_t Ncp, amp, *prach, *prach2, *prachF, *Xu; int32_t Xu_re, Xu_im, samp_count; int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k; @@ -122,6 +124,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach_start = slot*samp_count - ue->N_TA_offset; #endif + if (prach_start<0) prach_start += (fp->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME); @@ -428,20 +431,20 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach2 = prach+(Ncp<<1); if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { //24576 samples @ 30.72 Ms/s, 49152 samples @ 61.44 Ms/s - idft49152(prachF,prach2,1); + idft(IDFT_49152,prachF,prach2,1); // here we have |empty | Prach49152| memmove(prach,prach+(49152<<1),(Ncp<<2)); // here we have |Prefix | Prach49152| prach_len = 49152+Ncp; } else if (prach_fmt_id == 1) { //24576 samples @ 30.72 Ms/s, 49152 samples @ 61.44 Ms/s - idft49152(prachF,prach2,1); + idft(IDFT_49152,prachF,prach2,1); memmove(prach2+(49152<<1),prach2,(49152<<2)); // here we have |empty | Prach49152 | Prach49152| memmove(prach,prach+(49152<<2),(Ncp<<2)); // here we have |Prefix | Prach49152 | Prach49152| prach_len = (49152*2)+Ncp; } else if (prach_fmt_id == 2) { //24576 samples @ 30.72 Ms/s, 49152 samples @ 61.44 Ms/s - idft49152(prachF,prach2,1); + idft(IDFT_49152,prachF,prach2,1); memmove(prach2+(49152<<1),prach2,(49152<<2)); // here we have |empty | Prach49152 | Prach49152| empty49152 | empty49152 memmove(prach2+(49152<<2),prach2,(49152<<3)); @@ -450,7 +453,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach49152 | Prach49152| Prach49152 | Prach49152 prach_len = (49152*4)+Ncp; } else if (prach_fmt_id == 3) { // //6144 samples @ 30.72 Ms/s, 12288 samples @ 61.44 Ms/s - idft12288(prachF,prach2,1); + idft(IDFT_12288,prachF,prach2,1); memmove(prach2+(12288<<1),prach2,(12288<<2)); // here we have |empty | Prach12288 | Prach12288| empty12288 | empty12288 memmove(prach2+(12288<<2),prach2,(12288<<3)); @@ -463,7 +466,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) { Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft2048(prachF,prach2,1); + idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | if (prach_fmt_id != 7) { memmove(prach2+(2048<<1),prach2,(2048<<2)); @@ -475,7 +478,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 6x2048 Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft2048(prachF,prach2,1); + idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | memmove(prach2+(2048<<1),prach2,(2048<<2)); // here we have |empty | Prach2048 | Prach2048| empty2048 | empty2048 | @@ -487,7 +490,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x2048 Ncp+=32; prach2 = prach+(Ncp<<1); - idft2048(prachF,prach2,1); + idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | memmove(prach2+(2048<<1),prach2,(2048<<2)); // here we have |empty | Prach2048 | Prach2048| empty2048 | empty2048 | empty2048 | empty2048 @@ -501,7 +504,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 6) { // 12x2048 Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft2048(prachF,prach2,1); + idft(IDFT_2048,prachF,prach2,1); // here we have |empty | Prach2048 | memmove(prach2+(2048<<1),prach2,(2048<<2)); // here we have |empty | Prach2048 | Prach2048| empty2048 | empty2048 | empty2048 | empty2048 @@ -521,20 +524,20 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach2 = prach+(Ncp<<1); if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { - idft36864(prachF,prach2,1); + idft(IDFT_36864,prachF,prach2,1); // here we have |empty | Prach73728| memmove(prach,prach+(36864<<1),(Ncp<<2)); // here we have |Prefix | Prach73728| prach_len = (36864*1)+Ncp; } else if (prach_fmt_id == 1) { - idft36864(prachF,prach2,1); + idft(IDFT_36864,prachF,prach2,1); memmove(prach2+(36864<<1),prach2,(36864<<2)); // here we have |empty | Prach73728 | Prach73728| memmove(prach,prach+(36864<<2),(Ncp<<2)); // here we have |Prefix | Prach73728 | Prach73728| prach_len = (36864*2)+Ncp; } else if (prach_fmt_id == 2) { - idft36864(prachF,prach2,1); + idft(IDFT_36864,prachF,prach2,1); memmove(prach2+(36864<<1),prach2,(36864<<2)); // here we have |empty | Prach73728 | Prach73728| empty73728 | empty73728 memmove(prach2+(36864<<2),prach2,(36864<<3)); @@ -543,7 +546,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach73728 | Prach73728| Prach73728 | Prach73728 prach_len = (36864*4)+Ncp; } else if (prach_fmt_id == 3) { - idft9216(prachF,prach2,1); + idft(IDFT_9216,prachF,prach2,1); memmove(prach2+(9216<<1),prach2,(9216<<2)); // here we have |empty | Prach9216 | Prach9216| empty9216 | empty9216 memmove(prach2+(9216<<2),prach2,(9216<<3)); @@ -556,8 +559,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) { Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft1536(prachF,prach2,1); - + idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | if (prach_fmt_id != 7) { memmove(prach2+(1536<<1),prach2,(1536<<2)); @@ -571,7 +573,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft1536(prachF,prach2,1); + idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | memmove(prach2+(1536<<1),prach2,(1536<<2)); // here we have |empty | Prach1536 | Prach1536| empty1536 | empty1536 | @@ -583,7 +585,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 2 || 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); - idft1536(prachF,prach2,1); + idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | memmove(prach2+(1536<<1),prach2,(1536<<2)); // here we have |empty | Prach1536 | Prach1536| empty1536 | empty1536 | empty1536 | empty1536 @@ -597,7 +599,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 6) { // 12x1536 Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft1536(prachF,prach2,1); + idft(IDFT_1536,prachF,prach2,1); // here we have |empty | Prach1536 | memmove(prach2+(1536<<1),prach2,(1536<<2)); // here we have |empty | Prach1536 | Prach1536| empty1536 | empty1536 | empty1536 | empty1536 @@ -619,20 +621,20 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach2 = prach+(Ncp<<1); if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { //24576 samples @ 30.72 Ms/s, 98304 samples @ 122.88 Ms/s - idft98304(prachF,prach2,1); + idft(IDFT_98304,prachF,prach2,1); // here we have |empty | Prach98304| memmove(prach,prach+(98304<<1),(Ncp<<2)); // here we have |Prefix | Prach98304| prach_len = (98304*1)+Ncp; } else if (prach_fmt_id == 1) { - idft98304(prachF,prach2,1); + idft(IDFT_98304,prachF,prach2,1); memmove(prach2+(98304<<1),prach2,(98304<<2)); // here we have |empty | Prach98304 | Prach98304| memmove(prach,prach+(98304<<2),(Ncp<<2)); // here we have |Prefix | Prach98304 | Prach98304| prach_len = (98304*2)+Ncp; } else if (prach_fmt_id == 2) { - idft98304(prachF,prach2,1); + idft(IDFT_98304,prachF,prach2,1); memmove(prach2+(98304<<1),prach2,(98304<<2)); // here we have |empty | Prach98304 | Prach98304| empty98304 | empty98304 memmove(prach2+(98304<<2),prach2,(98304<<3)); @@ -641,7 +643,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach98304 | Prach98304| Prach98304 | Prach98304 prach_len = (98304*4)+Ncp; } else if (prach_fmt_id == 3) { // 4x6144, Ncp 3168 - idft24576(prachF,prach2,1); + idft(IDFT_24576,prachF,prach2,1); memmove(prach2+(24576<<1),prach2,(24576<<2)); // here we have |empty | Prach24576 | Prach24576| empty24576 | empty24576 memmove(prach2+(24576<<2),prach2,(24576<<3)); @@ -654,7 +656,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) { Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft4096(prachF,prach2,1); + idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | if (prach_fmt_id != 7) { memmove(prach2+(4096<<1),prach2,(4096<<2)); @@ -665,7 +667,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 4x4096 Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft4096(prachF,prach2,1); + idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | memmove(prach2+(4096<<1),prach2,(4096<<2)); // here we have |empty | Prach4096 | Prach4096| empty4096 | empty4096 | @@ -677,7 +679,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x4096 Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft4096(prachF,prach2,1); + idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | memmove(prach2+(4096<<1),prach2,(4096<<2)); // here we have |empty | Prach4096 | Prach4096| empty4096 | empty4096 | empty4096 | empty4096 @@ -691,7 +693,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 6) { // 12x4096 Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft4096(prachF,prach2,1); + idft(IDFT_4096,prachF,prach2,1); // here we have |empty | Prach4096 | memmove(prach2+(4096<<1),prach2,(4096<<2)); // here we have |empty | Prach4096 | Prach4096| empty4096 | empty4096 | empty4096 | empty4096 @@ -711,20 +713,20 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ prach2 = prach+(Ncp<<1); if (prach_sequence_length == 0){ if (prach_fmt_id == 0) { - idft73728(prachF,prach2,1); + idft(IDFT_73728,prachF,prach2,1); // here we have |empty | Prach73728| memmove(prach,prach+(73728<<1),(Ncp<<2)); // here we have |Prefix | Prach73728| prach_len = (73728*1)+Ncp; } else if (prach_fmt_id == 1) { - idft73728(prachF,prach2,1); + idft(IDFT_73728,prachF,prach2,1); memmove(prach2+(73728<<1),prach2,(73728<<2)); // here we have |empty | Prach73728 | Prach73728| memmove(prach,prach+(73728<<2),(Ncp<<2)); // here we have |Prefix | Prach73728 | Prach73728| prach_len = (73728*2)+Ncp; } if (prach_fmt_id == 2) { - idft73728(prachF,prach2,1); + idft(IDFT_73728,prachF,prach2,1); memmove(prach2+(73728<<1),prach2,(73728<<2)); // here we have |empty | Prach73728 | Prach73728| empty73728 | empty73728 memmove(prach2+(73728<<2),prach2,(73728<<3)); @@ -733,7 +735,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // here we have |Prefix | Prach73728 | Prach73728| Prach73728 | Prach73728 prach_len = (73728*4)+Ncp; } else if (prach_fmt_id == 3) { - idft18432(prachF,prach2,1); + idft(IDFT_18432,prachF,prach2,1); memmove(prach2+(18432<<1),prach2,(18432<<2)); // here we have |empty | Prach18432 | Prach18432| empty18432 | empty18432 memmove(prach2+(18432<<2),prach2,(18432<<3)); @@ -746,7 +748,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ if (prach_fmt_id == 0 || prach_fmt_id == 3 || prach_fmt_id == 7) { Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft3072(prachF,prach2,1); + idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | if (prach_fmt_id != 7) { memmove(prach2+(3072<<1),prach2,(3072<<2)); @@ -757,7 +759,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 2 || prach_fmt_id == 5) { // 6x3072 Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft3072(prachF,prach2,1); + idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | memmove(prach2+(3072<<1),prach2,(3072<<2)); // here we have |empty | Prach3072 | Prach3072| empty3072 | empty3072 | empty3072 | empty3072 @@ -771,7 +773,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else if (prach_fmt_id == 1 || prach_fmt_id == 4) { // 4x3072 Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling prach2 = prach+(Ncp<<1); - idft3072(prachF,prach2,1); + idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | memmove(prach2+(3072<<1),prach2,(3072<<2)); // here we have |empty | Prach3072 | Prach3072| empty3072 | empty3072 | @@ -783,7 +785,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } 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); - idft3072(prachF,prach2,1); + idft(IDFT_3072,prachF,prach2,1); // here we have |empty | Prach3072 | memmove(prach2+(3072<<1),prach2,(3072<<2)); // here we have |empty | Prach3072 | Prach3072| empty3072 | empty3072 | empty3072 | empty3072 diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 2e4f92d2cf..5cc8a2b6aa 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -60,17 +60,16 @@ void free_nr_ue_ulsch(NR_UE_ULSCH_t **ulschptr,unsigned char N_RB_UL) a_segments = a_segments/273; } - uint16_t ulsch_bytes = a_segments*1056; // allocated bytes per segment for (i=0; iharq_processes[i]) { if (ulsch->harq_processes[i]->a) { - free16(ulsch->harq_processes[i]->a,ulsch_bytes); + free16(ulsch->harq_processes[i]->a,a_segments*1056); ulsch->harq_processes[i]->a = NULL; } if (ulsch->harq_processes[i]->b) { - free16(ulsch->harq_processes[i]->b,ulsch_bytes); + free16(ulsch->harq_processes[i]->b,a_segments*1056); ulsch->harq_processes[i]->b = NULL; } if (ulsch->harq_processes[i]->e) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 769cea37a1..b84726c82d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -116,7 +116,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint16_t beta_ptrs; // PTRS parameter related to power control NR_UE_ULSCH_t *ulsch_ue; - NR_UL_UE_HARQ_t *harq_process_ul_ue; + NR_UL_UE_HARQ_t *harq_process_ul_ue=NULL; NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; NR_UE_PUSCH *pusch_ue = UE->pusch_vars[thread_id][gNB_id]; uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index e8eceb77a6..baf34ade92 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -52,7 +52,7 @@ * * PARAMETERS : size of ofdm symbol * -* RETURN : function idft +* RETURN : index pointing to the dft func in the dft library * * DESCRIPTION : get idft function depending of ofdm size * @@ -60,45 +60,45 @@ //#define DBG_PSS_NR -void *get_idft(int ofdm_symbol_size) +idft_size_idx_t get_idft(int ofdm_symbol_size) { - void (*idft)(int16_t *,int16_t *, int); - + + switch (ofdm_symbol_size) { case 128: - idft = idft128; + return IDFT_128; break; case 256: - idft = idft256; + return IDFT_256; break; case 512: - idft = idft512; + return IDFT_512; break; case 1024: - idft = idft1024; + return IDFT_1024; break; case 1536: - idft = idft1536; + return IDFT_1536; break; case 2048: - idft = idft2048; + return IDFT_2048; break; case 3072: - idft = idft3072; + return IDFT_3072; break; case 4096: - idft = idft4096; + return IDFT_4096; break; case 8192: - idft = idft8192; + return IDFT_8192; break; default: @@ -106,7 +106,7 @@ void *get_idft(int ofdm_symbol_size) assert(0); break; } - return idft; + return IDFT_SIZE_IDXTABLESIZE; // never reached and will trigger assertion in idft function } /******************************************************************* @@ -121,41 +121,41 @@ void *get_idft(int ofdm_symbol_size) * *********************************************************************/ -void *get_dft(int ofdm_symbol_size) +dft_size_idx_t get_dft(int ofdm_symbol_size) { - void (*dft)(int16_t *,int16_t *, int); + switch (ofdm_symbol_size) { case 128: - dft = dft128; + return DFT_128; break; case 256: - dft = dft256; + return DFT_256; break; case 512: - dft = dft512; + return DFT_512; break; case 1024: - dft = dft1024; + return DFT_1024; break; case 1536: - dft = dft1536; + return DFT_1536; break; case 2048: - dft = dft2048; + return DFT_2048; break; case 4096: - dft = dft4096; + return DFT_4096; break; case 8192: - dft = dft8192; + return DFT_8192; break; default: @@ -163,7 +163,7 @@ void *get_dft(int ofdm_symbol_size) assert(0); break; } - return dft; + return DFT_SIZE_IDXTABLESIZE; // never reached and will trigger assertion in idft function; } /******************************************************************* @@ -191,7 +191,7 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) unsigned int size = length * IQ_SIZE; /* i & q */ int16_t *primary_synchro = primary_synchro_nr[N_ID_2]; /* pss in complex with alternatively i then q */ int16_t *primary_synchro2 = primary_synchro_nr2[N_ID_2]; /* pss in complex with alternatively i then q */ - void (*idft)(int16_t *,int16_t *, int); + #define INITIAL_PSS_NR (7) const int x_initial[INITIAL_PSS_NR] = {0, 1, 1 , 0, 1, 1, 1}; @@ -282,9 +282,10 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) /* IFFT will give temporal signal of Pss */ - idft = get_idft(length); - - idft(synchroF_tmp, /* complex input */ + + + idft((int16_t)get_idft(length), + synchroF_tmp, /* complex input */ synchro_tmp, /* complex output */ 1); /* scaling factor */ @@ -312,6 +313,7 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) #endif + #if 0 /* it allows checking that process of idft on a signal and then dft gives same signal with limited errors */ @@ -323,10 +325,11 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp,int N_ID_2) bzero(synchroF_tmp, size); - void (*dft)(int16_t *,int16_t *, int) = get_dft(length); + /* get pss in the time domain by applying an inverse FFT */ - dft(synchro_tmp, /* complex input */ + dft((int16_t)get_dft(length), + synchro_tmp, /* complex input */ synchroF_tmp, /* complex output */ 1); /* scaling factor */ diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index d63cef5085..2a08d54c5a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -42,6 +42,7 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "T.h" +//#define NR_UNIT_TEST 1 #ifdef NR_UNIT_TEST #define DEBUG_PUCCH_TX #define DEBUG_NR_PUCCH_TX @@ -905,7 +906,9 @@ void nr_uci_encoding(uint64_t payload, if (A<=11) { // procedure in subclause 6.3.1.2.2 (UCI encoded by channel coding of small block lengths -> subclause 6.3.1.3.2) // CRC bits are not attached, and coding small block lengths (subclause 5.3.3) + b[0] = encodeSmallBlock((uint16_t*)&payload,A); } else if (A>=12) { + AssertFatal(1==0,"Polar encoding not supported yet for UCI\n"); // procedure in subclause 6.3.1.2.1 (UCI encoded by Polar code -> subclause 6.3.1.3.1) /*if ((A>=360 && E>=1088)||(A>=1013)) { I_seg = 1; @@ -924,10 +927,13 @@ void nr_uci_encoding(uint64_t payload, // code block segmentation and CRC attachment is performed according to subclause 5.2.1 // polar coding subclause 5.3.1 } + } //#if 0 void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint16_t crnti, + uint32_t dmrs_scrambling_id, + uint32_t data_scrambling_id, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, @@ -961,14 +967,14 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, */ uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI - uint16_t rnti=crnti, n_id=0; + uint16_t rnti=crnti; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch2] rnti = %d ,\n",rnti); #endif /* * Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2 */ - nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,b,btilde); + nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,b,btilde); /* * Implementing TS 38.211 Subclause 6.3.2.5.2 modulation format 2 * btilde shall be modulated as described in subclause 5.1 using QPSK @@ -1016,10 +1022,10 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, int m=0; for (int l=0; lN_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h index 4c4847d7de..a2446dccf9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h @@ -20,7 +20,7 @@ */ /*! \file PHY/NR_UE_TRANSPORT/pucch_nr.c -* \brief Top-level routines for generating and decoding the PUCCH physical channel +* \brief Top-level routines for generating the PUCCH physical channel * \author A. Mico Pereperez * \date 2018 * \version 0.1 @@ -29,6 +29,9 @@ * \note * \warning */ +#ifndef __PUCCH_NR__H__ +#define __PUCCH_NR__H__ + //#include "PHY/defs.h" #include "PHY/impl_defs_nr.h" #include "PHY/defs_nr_common.h" @@ -70,6 +73,8 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, uint8_t nr_bit); void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint16_t crnti, + uint32_t dmrs_scrambling_id, + uint32_t data_scrambling_id, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, @@ -415,3 +420,4 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, 73, 79, 83, 89, 97, 101,103,107,109,113, 127,131,137,139,149,151,157,163,167,173, 179,181,191,193,197,199}; +#endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 44d500b0b7..e3f1f13a8d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -182,7 +182,7 @@ void insert_sss_nr(int16_t *sss_time, } /* get sss in the frequency domain by applying an inverse FFT */ - idft2048(synchroF_tmp, /* complex input */ + idft(IDFT_2048,synchroF_tmp, /* complex input */ synchro_tmp, /* complex output */ 1); /* scaling factor */ diff --git a/openair1/PHY/TOOLS/dfts_load.c b/openair1/PHY/TOOLS/dfts_load.c new file mode 100644 index 0000000000..d758f46a43 --- /dev/null +++ b/openair1/PHY/TOOLS/dfts_load.c @@ -0,0 +1,65 @@ +/* + * 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 openair1/PHY/CODING/coding_nr_load.c + * \brief: load library implementing coding/decoding algorithms + * \author Francois TABURET + * \date 2020 + * \version 0.1 + * \company NOKIA BellLabs France + * \email: francois.taburet@nokia-bell-labs.com + * \note + * \warning + */ +#define _GNU_SOURCE +#include +#include +#include +#include "assertions.h" +#include "common/utils/LOG/log.h" +#define OAIDFTS_LOADER +#include "tools_defs.h" +#include "common/config/config_userapi.h" +#include "common/utils/load_module_shlib.h" + + +/* function description array, to be used when loading the dfts/idfts lib */ +static loader_shlibfunc_t shlib_fdesc[2]; +static char *arg[64]={"phytest","-O","cmdlineonly::dbgl0"}; + + +int load_dftslib(void) { + + char *ptr = (char*)config_get_if(); + if ( ptr==NULL ) {// phy simulators, config module possibly not loaded + load_configmodule(3,(char **)arg,CONFIG_ENABLECMDLINEONLY) ; + logInit(); + } + shlib_fdesc[0].fname = "dft"; + shlib_fdesc[1].fname = "idft"; + int ret=load_module_shlib("dfts",shlib_fdesc,sizeof(shlib_fdesc)/sizeof(loader_shlibfunc_t),NULL); + AssertFatal( (ret >= 0),"Error loading dftsc decoder"); + dft = (dftfunc_t)shlib_fdesc[0].fptr; + idft = (idftfunc_t)shlib_fdesc[1].fptr; +return 0; +} + + diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index dbcd9540be..8621898d9d 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -325,12 +325,18 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, // PUSCH I/Q of MF Output if (pusch_comp!=NULL) { ind=0; + int range=80*1000*1000; for (k=0; ksymbols_per_tti; k++) { for (i=0; i<12*frame_parms->N_RB_UL; i++) { - I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; - Q[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1]; - ind++; + if ( pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i] > -range && + pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i] < range && + pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1] > -range && + pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1] < range ) { + I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; + Q[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1]; + ind++; + } } } diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index e0fa894d92..67ec027a9d 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -182,7 +182,7 @@ void phy_scope_gNB(FD_phy_scope_gnb *form, int Qm = 2; /* - if (!RC.nrmac[0]->UE_list.active[UE_id]) + if (!RC.nrmac[0]->UE_info.active[UE_id]) return; // choose max MCS to compute coded_bits_per_codeword diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/oai_dfts.c similarity index 98% rename from openair1/PHY/TOOLS/lte_dfts.c rename to openair1/PHY/TOOLS/oai_dfts.c index 4baf996f7c..bb8c46592c 100644 --- a/openair1/PHY/TOOLS/lte_dfts.c +++ b/openair1/PHY/TOOLS/oai_dfts.c @@ -31,11 +31,10 @@ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif - +#define OAIDFTS_MAIN #ifndef MR_MAIN #include "PHY/defs_common.h" #include "PHY/impl_defs_top.h" -#include "tools_defs.h" #else #include "time_meas.h" #include "LOG/log.h" @@ -64,6 +63,9 @@ const static int16_t reflip[32] __attribute__((aligned(32))) = {1,-1,1,-1,1,-1, + + + #if defined(__x86_64__) || defined(__i386__) static inline void cmac(__m128i a,__m128i b, __m128i *re32, __m128i *im32) __attribute__((always_inline)); static inline void cmac(__m128i a,__m128i b, __m128i *re32, __m128i *im32) @@ -2592,7 +2594,7 @@ const static int16_t tw64c[96] __attribute__((aligned(32))) = { #endif #ifndef __AVX2__ -void dft64(int16_t *x,int16_t *y,int scale) +void dft64(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[16],ytmp[16],*tw64a_128=(simd_q15_t *)tw64a,*tw64b_128=(simd_q15_t *)tw64b,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y; @@ -2706,7 +2708,7 @@ void dft64(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void dft64(int16_t *x,int16_t *y,int scale) +void dft64(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],ytmp[16],*tw64a_256=(simd256_q15_t *)tw64a,*tw64b_256=(simd256_q15_t *)tw64b,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y; @@ -2854,7 +2856,7 @@ void dft64(int16_t *x,int16_t *y,int scale) #endif #ifndef __AVX2__ -void idft64(int16_t *x,int16_t *y,int scale) +void idft64(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[16],ytmp[16],*tw64a_128=(simd_q15_t *)tw64,*tw64b_128=(simd_q15_t *)tw64c,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y; @@ -2946,7 +2948,7 @@ void idft64(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void idft64(int16_t *x,int16_t *y,int scale) +void idft64(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],ytmp[16],*tw64a_256=(simd256_q15_t *)tw64,*tw64b_256=(simd256_q15_t *)tw64c,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y; @@ -3056,7 +3058,7 @@ int16_t tw128b[128] __attribute__((aligned(32))) = {0,32767,-1608,32727,-3212,32 int16_t tw128c[128] __attribute__((aligned(32))) = {0,32767,1608,32727,3212,32609,4808,32412,6393,32137,7962,31785,9512,31356,11039,30851,12540,30272,14010,29621,15447,28897,16846,28105,18205,27244,19520,26318,20788,25329,22005,24278,23170,23169,24279,22004,25330,20787,26319,19519,27245,18204,28106,16845,28898,15446,29622,14009,30273,12539,30852,11038,31357,9511,31786,7961,32138,6392,32413,4807,32610,3211,32728,1607,32767,0,32728,-1608,32610,-3212,32413,-4808,32138,-6393,31786,-7962,31357,-9512,30852,-11039,30273,-12540,29622,-14010,28898,-15447,28106,-16846,27245,-18205,26319,-19520,25330,-20788,24279,-22005,23170,-23170,22005,-24279,20788,-25330,19520,-26319,18205,-27245,16846,-28106,15447,-28898,14010,-29622,12540,-30273,11039,-30852,9512,-31357,7962,-31786,6393,-32138,4808,-32413,3212,-32610,1608,-32728}; #ifndef __AVX2__ -void dft128(int16_t *x,int16_t *y,int scale) +void dft128(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[64],*x64 = (simdshort_q15_t *)x; @@ -3163,7 +3165,7 @@ void dft128(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void dft128(int16_t *x,int16_t *y,int scale) +void dft128(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],*x256 = (simd256_q15_t *)x; @@ -3233,7 +3235,7 @@ void dft128(int16_t *x,int16_t *y,int scale) #endif #ifndef __AVX2__ -void idft128(int16_t *x,int16_t *y,int scale) +void idft128(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[64],*x64 = (simdshort_q15_t *)x; @@ -3332,7 +3334,7 @@ void idft128(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void idft128(int16_t *x,int16_t *y,int scale) +void idft128(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],*x256 = (simd256_q15_t *)x; @@ -3405,7 +3407,7 @@ int16_t tw256b[384] __attribute__((aligned(32))) = {0,32767,-805,32757,-1608,327 0,32767,-2411,32678,-4808,32412,-7180,31970,-9512,31356,-11793,30571,-14010,29621,-16151,28510,-18205,27244,-20160,25831,-22005,24278,-23732,22594,-25330,20787,-26790,18867,-28106,16845,-29269,14732,-30273,12539,-31114,10278,-31786,7961,-32285,5601,-32610,3211,-32758,804,-32728,-1608,-32521,-4012,-32138,-6393,-31581,-8740,-30852,-11039,-29956,-13279,-28898,-15447,-27684,-17531,-26319,-19520,-24812,-21403,-23170,-23170,-21403,-24812,-19520,-26319,-17531,-27684,-15447,-28898,-13279,-29956,-11039,-30852,-8740,-31581,-6393,-32138,-4012,-32521,-1608,-32728,804,-32758,3211,-32610,5601,-32285,7961,-31786,10278,-31114,12539,-30273,14732,-29269,16845,-28106,18867,-26790,20787,-25330,22594,-23732,24278,-22005,25831,-20160,27244,-18205,28510,-16151,29621,-14010,30571,-11793,31356,-9512,31970,-7180,32412,-4808,32678,-2411 }; #ifndef __AVX2__ -void dft256(int16_t *x,int16_t *y,int scale) +void dft256(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[64],ytmp[64],*tw256a_128p=(simd_q15_t *)tw256a,*tw256b_128p=(simd_q15_t *)tw256b,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -3517,7 +3519,7 @@ void dft256(int16_t *x,int16_t *y,int scale) -void idft256(int16_t *x,int16_t *y,int scale) +void idft256(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[64],ytmp[64],*tw256_128p=(simd_q15_t *)tw256,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -3575,7 +3577,7 @@ void idft256(int16_t *x,int16_t *y,int scale) #else //__AVX2__ -void dft256(int16_t *x,int16_t *y,int scale) +void dft256(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[32],ytmp[32],*tw256a_256p=(simd256_q15_t *)tw256a,*tw256b_256p=(simd256_q15_t *)tw256b,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -3667,7 +3669,7 @@ void dft256(int16_t *x,int16_t *y,int scale) } -void idft256(int16_t *x,int16_t *y,int scale) +void idft256(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[32],ytmp[32],*tw256_256p=(simd256_q15_t *)tw256,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -3772,7 +3774,7 @@ int16_t tw512c[512] __attribute__((aligned(32))) = { }; #ifndef __AVX2__ -void dft512(int16_t *x,int16_t *y,int scale) +void dft512(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[256],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -3892,7 +3894,7 @@ void dft512(int16_t *x,int16_t *y,int scale) } -void idft512(int16_t *x,int16_t *y,int scale) +void idft512(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[256],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -3984,7 +3986,7 @@ void idft512(int16_t *x,int16_t *y,int scale) #else //__AVX2__ -void dft512(int16_t *x,int16_t *y,int scale) +void dft512(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[64],*x256 = (simd256_q15_t *)x; @@ -4066,7 +4068,7 @@ void dft512(int16_t *x,int16_t *y,int scale) } -void idft512(int16_t *x,int16_t *y,int scale) +void idft512(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[64],*x256 = (simd256_q15_t *)x; @@ -4153,7 +4155,7 @@ void idft512(int16_t *x,int16_t *y,int scale) int16_t tw1024[1536] __attribute__((aligned(32))); #ifndef __AVX2__ -void dft1024(int16_t *x,int16_t *y,int scale) +void dft1024(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[256],ytmp[256],*tw1024_128p=(simd_q15_t *)tw1024,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4209,7 +4211,7 @@ void dft1024(int16_t *x,int16_t *y,int scale) } -void idft1024(int16_t *x,int16_t *y,int scale) +void idft1024(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[256],ytmp[256],*tw1024_128p=(simd_q15_t *)tw1024,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4266,7 +4268,7 @@ void idft1024(int16_t *x,int16_t *y,int scale) } #else //__AVX2__ -void dft1024(int16_t *x,int16_t *y,int scale) +void dft1024(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[128],ytmp[128],*tw1024_256p=(simd256_q15_t *)tw1024,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4322,7 +4324,7 @@ void dft1024(int16_t *x,int16_t *y,int scale) } -void idft1024(int16_t *x,int16_t *y,int scale) +void idft1024(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[128],ytmp[128],*tw1024_256p=(simd256_q15_t *)tw1024,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4382,7 +4384,7 @@ void idft1024(int16_t *x,int16_t *y,int scale) int16_t tw2048[2048] __attribute__((aligned(32))); #ifndef __AVX2__ -void dft2048(int16_t *x,int16_t *y,int scale) +void dft2048(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[1024],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -4473,7 +4475,7 @@ void dft2048(int16_t *x,int16_t *y,int scale) } -void idft2048(int16_t *x,int16_t *y,int scale) +void idft2048(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[1024],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -4565,7 +4567,7 @@ void idft2048(int16_t *x,int16_t *y,int scale) #else // __AVX2__ -void dft2048(int16_t *x,int16_t *y,int scale) +void dft2048(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[256],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -4656,7 +4658,7 @@ void dft2048(int16_t *x,int16_t *y,int scale) } -void idft2048(int16_t *x,int16_t *y,int scale) +void idft2048(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[256],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -4753,7 +4755,7 @@ void idft2048(int16_t *x,int16_t *y,int scale) int16_t tw4096[3*2*1024]; #ifndef __AVX2__ -void dft4096(int16_t *x,int16_t *y,int scale) +void dft4096(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[1024],ytmp[1024],*tw4096_128p=(simd_q15_t *)tw4096,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4811,7 +4813,7 @@ void dft4096(int16_t *x,int16_t *y,int scale) -void idft4096(int16_t *x,int16_t *y,int scale) +void idft4096(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[1024],ytmp[1024],*tw4096_128p=(simd_q15_t *)tw4096,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4868,7 +4870,7 @@ void idft4096(int16_t *x,int16_t *y,int scale) } #else //__AVX2__ -void dft4096(int16_t *x,int16_t *y,int scale) +void dft4096(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[512],ytmp[512],*tw4096_256p=(simd256_q15_t *)tw4096,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4924,7 +4926,7 @@ void dft4096(int16_t *x,int16_t *y,int scale) } -void idft4096(int16_t *x,int16_t *y,int scale) +void idft4096(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[512],ytmp[512],*tw4096_256p=(simd256_q15_t *)tw4096,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4986,7 +4988,7 @@ void idft4096(int16_t *x,int16_t *y,int scale) int16_t tw8192[2*4096] __attribute__((aligned(32))); #ifndef __AVX2__ -void dft8192(int16_t *x,int16_t *y,int scale) +void dft8192(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[4096],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -5076,7 +5078,7 @@ void dft8192(int16_t *x,int16_t *y,int scale) } -void idft8192(int16_t *x,int16_t *y,int scale) +void idft8192(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[4096],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -5167,7 +5169,7 @@ void idft8192(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void dft8192(int16_t *x,int16_t *y,int scale) +void dft8192(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[1024],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -5258,7 +5260,7 @@ void dft8192(int16_t *x,int16_t *y,int scale) } -void idft8192(int16_t *x,int16_t *y,int scale) +void idft8192(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[1024],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -5354,7 +5356,7 @@ void idft8192(int16_t *x,int16_t *y,int scale) int16_t twa1536[1024],twb1536[1024]; // 512 x 3 -void idft1536(int16_t *input, int16_t *output, int scale) +void idft1536(int16_t *input, int16_t *output, unsigned char scale) { int i,i2,j; uint32_t tmp[3][512 ]__attribute__((aligned(32))); @@ -5406,7 +5408,7 @@ void idft1536(int16_t *input, int16_t *output, int scale) } -void dft1536(int16_t *input, int16_t *output, int scale) +void dft1536(int16_t *input, int16_t *output, unsigned char scale) { int i,i2,j; uint32_t tmp[3][512] __attribute__((aligned(32))); @@ -5471,7 +5473,7 @@ void dft1536(int16_t *input, int16_t *output, int scale) int16_t twa3072[2048] __attribute__((aligned(32))); int16_t twb3072[2048] __attribute__((aligned(32))); // 1024 x 3 -void dft3072(int16_t *input, int16_t *output,int scale) +void dft3072(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][1024] __attribute__((aligned(32))); @@ -5521,7 +5523,7 @@ void dft3072(int16_t *input, int16_t *output,int scale) _m_empty(); } -void idft3072(int16_t *input, int16_t *output,int scale) +void idft3072(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][1024]__attribute__((aligned(32))); @@ -5575,7 +5577,7 @@ void idft3072(int16_t *input, int16_t *output,int scale) int16_t twa6144[4096] __attribute__((aligned(32))); int16_t twb6144[4096] __attribute__((aligned(32))); -void idft6144(int16_t *input, int16_t *output,int scale) +void idft6144(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][2048] __attribute__((aligned(32))); @@ -5635,7 +5637,7 @@ void idft6144(int16_t *input, int16_t *output,int scale) } -void dft6144(int16_t *input, int16_t *output,int scale) +void dft6144(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][2048] __attribute__((aligned(32))); @@ -5699,12 +5701,12 @@ void dft6144(int16_t *input, int16_t *output,int scale) int16_t twa9216[6144] __attribute__((aligned(32))); int16_t twb9216[6144] __attribute__((aligned(32))); // 3072 x 3 -void dft9216(int16_t *input, int16_t *output,int scale) { +void dft9216(int16_t *input, int16_t *output,uint8_t scale) { AssertFatal(1==0,"Need to do this ..\n"); } -void idft9216(int16_t *input, int16_t *output,int scale) { +void idft9216(int16_t *input, int16_t *output,uint8_t scale) { AssertFatal(1==0,"Need to do this ..\n"); } @@ -5712,7 +5714,7 @@ void idft9216(int16_t *input, int16_t *output,int scale) { int16_t twa12288[8192] __attribute__((aligned(32))); int16_t twb12288[8192] __attribute__((aligned(32))); // 4096 x 3 -void dft12288(int16_t *input, int16_t *output,int scale) +void dft12288(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][4096] __attribute__((aligned(32))); @@ -5772,7 +5774,7 @@ void dft12288(int16_t *input, int16_t *output,int scale) } -void idft12288(int16_t *input, int16_t *output,int scale) +void idft12288(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][4096] __attribute__((aligned(32))); @@ -5836,7 +5838,7 @@ void idft12288(int16_t *input, int16_t *output,int scale) int16_t twa18432[12288] __attribute__((aligned(32))); int16_t twb18432[12288] __attribute__((aligned(32))); // 6144 x 3 -void dft18432(int16_t *input, int16_t *output,int scale) { +void dft18432(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][6144] __attribute__((aligned(32))); @@ -5884,7 +5886,7 @@ void dft18432(int16_t *input, int16_t *output,int scale) { _m_empty(); } -void idft18432(int16_t *input, int16_t *output,int scale) { +void idft18432(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][6144] __attribute__((aligned(32))); @@ -5936,7 +5938,7 @@ void idft18432(int16_t *input, int16_t *output,int scale) { int16_t twa24576[16384] __attribute__((aligned(32))); int16_t twb24576[16384] __attribute__((aligned(32))); // 8192 x 3 -void dft24576(int16_t *input, int16_t *output,int scale) +void dft24576(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][8192] __attribute__((aligned(32))); @@ -5999,7 +6001,7 @@ void dft24576(int16_t *input, int16_t *output,int scale) } } -void idft24576(int16_t *input, int16_t *output,int scale) +void idft24576(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][8192] __attribute__((aligned(32))); @@ -6062,7 +6064,7 @@ int16_t twa36864[24576] __attribute__((aligned(32))); int16_t twb36864[24576] __attribute__((aligned(32))); // 12288 x 3 -void dft36864(int16_t *input, int16_t *output,int scale) { +void dft36864(int16_t *input, int16_t *output,uint8_t scale) { int i,i2,j; uint32_t tmp[3][12288] __attribute__((aligned(32))); @@ -6120,7 +6122,7 @@ void dft36864(int16_t *input, int16_t *output,int scale) { } } -void idft36864(int16_t *input, int16_t *output,int scale) { +void idft36864(int16_t *input, int16_t *output,uint8_t scale) { int i,i2,j; uint32_t tmp[3][12288] __attribute__((aligned(32))); @@ -6172,14 +6174,12 @@ int16_t twa49152[32768] __attribute__((aligned(32))); int16_t twb49152[32768] __attribute__((aligned(32))); // 16384 x 3 -// TbD todo dft16384 -void dft49152(int16_t *input, int16_t *output,int scale) { +void dft49152(int16_t *input, int16_t *output,uint8_t scale) { AssertFatal(1==0,"Need to do this ..\n"); } -// TbD todo dft16384 -void idft49152(int16_t *input, int16_t *output,int scale) { +void idft49152(int16_t *input, int16_t *output,uint8_t scale) { AssertFatal(1==0,"Need to do this ..\n"); } @@ -6187,12 +6187,12 @@ void idft49152(int16_t *input, int16_t *output,int scale) { int16_t twa73728[49152] __attribute__((aligned(32))); int16_t twb73728[49152] __attribute__((aligned(32))); // 24576 x 3 -void dft73728(int16_t *input, int16_t *output,int scale) { +void dft73728(int16_t *input, int16_t *output,uint8_t scale) { AssertFatal(1==0,"Need to do this ..\n"); } -void idft73728(int16_t *input, int16_t *output,int scale) { +void idft73728(int16_t *input, int16_t *output,uint8_t scale) { AssertFatal(1==0,"Need to do this ..\n"); } @@ -6201,12 +6201,12 @@ void idft73728(int16_t *input, int16_t *output,int scale) { int16_t twa98304[49152] __attribute__((aligned(32))); int16_t twb98304[49152] __attribute__((aligned(32))); // 32768 x 3 -void dft98304(int16_t *input, int16_t *output,int scale) { +void dft98304(int16_t *input, int16_t *output,uint8_t scale) { AssertFatal(1==0,"Need to do this ..\n"); } -void idft98304(int16_t *input, int16_t *output,int scale) { +void idft98304(int16_t *input, int16_t *output,uint8_t scale) { AssertFatal(1==0,"Need to do this ..\n"); } @@ -6364,7 +6364,7 @@ static inline void dft12f(simd_q15_t *x0, -void dft12(int16_t *x,int16_t *y) +void dft12(int16_t *x,int16_t *y ,unsigned char scale_flag) { simd_q15_t *x128 = (simd_q15_t *)x,*y128 = (simd_q15_t *)y; @@ -8696,8 +8696,6 @@ void dft1200(int16_t *x,int16_t *y,unsigned char scale_flag) } -//#define round trunc - void init_rad4(int N,int16_t *tw) { int16_t *twa = tw; @@ -8813,12 +8811,13 @@ void init_rad5_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc,int16_t *twd) { twa+=8; twb+=8; twc+=8; - twd+=8; + twd+=8; } } +/*----------------------------------------------------------------*/ +/* dft library entry points: */ - -void init_dfts(void) +int dfts_autoinit(void) { init_rad4(1024,tw1024); init_rad2(2048,tw2048); @@ -8865,9 +8864,23 @@ void init_dfts(void) init_rad3_rep(1080,twa1080,twb1080); init_rad4_rep(1152,twa1152,twb1152,twc1152); init_rad4_rep(1200,twa1200,twb1200,twc1200); + return 0; } -//#undef round + + + +void dft(uint8_t sizeidx, int16_t *sigF,int16_t *sig,unsigned char scale_flag){ + AssertFatal((sizeidx>=0 && sizeidx<(int)DFT_SIZE_IDXTABLESIZE),"Invalid dft size index %i\n",sizeidx); + dft_ftab[sizeidx](sigF,sig,scale_flag); +}; + +void idft(uint8_t sizeidx, int16_t *sigF,int16_t *sig,unsigned char scale_flag){ + AssertFatal((sizeidx>=0 && sizeidx<(int)IDFT_SIZE_IDXTABLESIZE),"Invalid idft size index %i\n",sizeidx); + idft_ftab[sizeidx](sigF,sig,scale_flag); +}; + +/*---------------------------------------------------------------------------------------*/ #ifdef MR_MAIN #include @@ -9038,12 +9051,12 @@ int main(int argc, char**argv) #ifdef __AVX2__ simd256_q15_t x[4096],x2[4096],y[4096],tw0,tw1,tw2,tw3; #else - simd_q15_t x[8192],x2[8192],y[8192],tw0,tw1,tw2,tw3; + simd_q15_t x[8192],y[8192],tw0,tw1,tw2,tw3; #endif int i; simd_q15_t *x128=(simd_q15_t*)x,*y128=(simd_q15_t*)y; - init_dfts(); + dfts_autoinit(); set_taus_seed(0); opp_enabled = 1; diff --git a/openair1/PHY/TOOLS/time_meas.h b/openair1/PHY/TOOLS/time_meas.h index b9777686ea..2deab40f27 100644 --- a/openair1/PHY/TOOLS/time_meas.h +++ b/openair1/PHY/TOOLS/time_meas.h @@ -33,7 +33,7 @@ #include // global var to enable openair performance profiler extern int opp_enabled; -double cpu_freq_GHz; +double cpu_freq_GHz __attribute__ ((aligned(32)));; #if defined(__x86_64__) || defined(__i386__) typedef struct { diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 8e0406d07d..61ea785db8 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -36,6 +36,8 @@ extern "C" { #include #include "PHY/sse_intrin.h" +#define CEILIDIV(a,b) ((a+b-1)/b) +#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) struct complex { double x; @@ -179,46 +181,144 @@ This function performs optimized fixed-point radix-2 FFT/IFFT. ); */ -void idft16f(int16_t *x,int16_t *y); -void idft1536(int16_t *sigF,int16_t *sig,int scale); -void idft6144(int16_t *sigF,int16_t *sig,int scale); -void idft12288(int16_t *sigF,int16_t *sig,int scale); -void idft18432(int16_t *sigF,int16_t *sig,int scale); -void idft3072(int16_t *sigF,int16_t *sig,int scale); -void idft24576(int16_t *sigF,int16_t *sig,int scale); +#ifdef OAIDFTS_MAIN +typedef void(*adftfunc_t)(int16_t *sigF,int16_t *sig,unsigned char scale_flag); +typedef void(*aidftfunc_t)(int16_t *sigF,int16_t *sig,unsigned char scale_flag); -void dft1536(int16_t *sigF,int16_t *sig,int scale); +void dft12(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft24(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft36(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft48(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft60(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft64(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft72(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft96(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft108(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft120(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft128(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft144(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft180(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft192(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft216(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft240(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft256(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft288(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft300(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft324(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft360(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft384(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft432(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft480(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft512(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft540(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft576(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft600(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft648(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft720(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft768(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft864(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft900(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft960(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft972(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1024(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1080(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1152(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1200(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1536(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft2048(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft3072(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft4096(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft6144(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft8192(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft9216(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft12288(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft18432(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft24576(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft36864(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft49152(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft73728(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft98304(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft3072(int16_t *sigF,int16_t *sig,int scale); -void dft6144(int16_t *sigF,int16_t *sig,int scale); +void idft64(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft128(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft256(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft512(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft1024(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft1536(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft2048(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft3072(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft4096(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft6144(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft8192(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft9216(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft12288(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft18432(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft24576(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft36864(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft49152(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft73728(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft98304(int16_t *sigF,int16_t *sig,uint8_t scale_flag); -void dft12288(int16_t *sigF,int16_t *sig,int scale); -void dft18432(int16_t *sigF,int16_t *sig,int scale); -void dft24576(int16_t *sigF,int16_t *sig,int scale); -void dft49152(int16_t *sigF,int16_t *sig,int scale); -void idft49152(int16_t *sigF,int16_t *sig,int scale); +#else + typedef void(*dftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag); + typedef void(*idftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag); +# ifdef OAIDFTS_LOADER + dftfunc_t dft; + idftfunc_t idft; +# else + extern dftfunc_t dft; + extern idftfunc_t idft; + extern int load_dftslib(void); +# endif +#endif -void dft9216(int16_t *sigF,int16_t *sig,int scale); -void idft9216(int16_t *sigF,int16_t *sig,int scale); +typedef enum DFT_size_idx { + DFT_12, DFT_24, DFT_36, DFT_48, DFT_60, DFT_72, DFT_96, + DFT_108, DFT_120, DFT_128, DFT_144, DFT_180, DFT_192, DFT_216, DFT_240, + DFT_256, DFT_288, DFT_300, DFT_324, DFT_360, DFT_384, DFT_432, DFT_480, + DFT_512, DFT_540, DFT_576, DFT_600, DFT_648, DFT_720, DFT_768, DFT_864, + DFT_900, DFT_960, DFT_972, DFT_1024, DFT_1080, DFT_1152, DFT_1200, DFT_1536, + DFT_2048, DFT_3072, DFT_4096, DFT_6144, DFT_8192, DFT_9216, DFT_12288, DFT_18432, + DFT_24576, DFT_36864, DFT_49152, DFT_73728, DFT_98304, + DFT_SIZE_IDXTABLESIZE +} dft_size_idx_t; -void dft36864(int16_t *sigF,int16_t *sig,int scale); -void idft36864(int16_t *sigF,int16_t *sig,int scale); +#ifdef OAIDFTS_MAIN +adftfunc_t dft_ftab[]={ + dft12, dft24, dft36, dft48, dft60, dft72, dft96, + dft108, dft120, dft128, dft144, dft180, dft192, dft216, dft240, + dft256, dft288, dft300, dft324, dft360, dft384, dft432, dft480, + dft512, dft540, dft576, dft600, dft648, dft720, dft768, dft864, + dft900, dft960, dft972, dft1024, dft1080, dft1152, dft1200, dft1536, + dft2048, dft3072, dft4096, dft6144, dft8192, dft9216, dft12288, dft18432, + dft24576, dft36864, dft49152, dft73728, dft98304 +}; +#endif -void dft98304(int16_t *sigF,int16_t *sig,int scale); -void idft98304(int16_t *sigF,int16_t *sig,int scale); +typedef enum idft_size_idx { + IDFT_128, IDFT_256, IDFT_512, IDFT_1024, IDFT_1536, IDFT_2048, IDFT_3072, IDFT_4096, + IDFT_6144, IDFT_8192, IDFT_9216, IDFT_12288, IDFT_18432, IDFT_24576, IDFT_36864, IDFT_49152, + IDFT_73728, IDFT_98304, + IDFT_SIZE_IDXTABLESIZE +} idft_size_idx_t; +#ifdef OAIDFTS_MAIN +aidftfunc_t idft_ftab[]={ + idft128, idft256, idft512, idft1024, idft1536, idft2048, idft3072, idft4096, + idft6144, idft8192, idft9216, idft12288, idft18432, idft24576, idft36864, idft49152, + idft73728, idft98304 +}; +#endif -void dft73728(int16_t *sigF,int16_t *sig,int scale); -void idft73728(int16_t *sigF,int16_t *sig,int scale); /*!\fn int32_t rotate_cpx_vector(int16_t *x,int16_t *alpha,int16_t *y,uint32_t N,uint16_t output_shift) @@ -389,57 +489,7 @@ int64_t dot_product64(int16_t *x, uint32_t N, //must be a multiple of 8 uint8_t output_shift); -void dft12(int16_t *x,int16_t *y); -void dft24(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft36(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft48(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft60(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft72(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft96(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft108(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft120(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft144(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft180(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft192(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft216(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft240(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft288(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft300(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft324(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft360(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft384(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft432(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft480(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft540(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft576(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft600(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft648(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft720(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft768(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft864(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft900(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft960(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft972(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft1080(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft1152(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft1200(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft64(int16_t *x,int16_t *y,int scale); -void dft128(int16_t *x,int16_t *y,int scale); -void dft256(int16_t *x,int16_t *y,int scale); -void dft512(int16_t *x,int16_t *y,int scale); -void dft1024(int16_t *x,int16_t *y,int scale); -void dft2048(int16_t *x,int16_t *y,int scale); -void dft4096(int16_t *x,int16_t *y,int scale); -void dft8192(int16_t *x,int16_t *y,int scale); -void idft64(int16_t *x,int16_t *y,int scale); -void idft128(int16_t *x,int16_t *y,int scale); -void idft256(int16_t *x,int16_t *y,int scale); -void idft512(int16_t *x,int16_t *y,int scale); -void idft1024(int16_t *x,int16_t *y,int scale); -void idft2048(int16_t *x,int16_t *y,int scale); -void idft4096(int16_t *x,int16_t *y,int scale); -void idft8192(int16_t *x,int16_t *y,int scale); /** @} */ diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 7b06f6c8c7..557b8bfc30 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -201,41 +201,11 @@ typedef struct { int repetition_number[4]; } LTE_eNB_PRACH; -/// Context data structure for RX/TX portion of subframe processing -typedef struct { - /// Component Carrier index - uint8_t CC_id; - /// timestamp transmitted to HW - openair0_timestamp timestamp_tx; - /// subframe to act upon for transmission - int subframe_tx; - /// subframe to act upon for reception - int subframe_rx; - /// frame to act upon for transmission - int frame_tx; - /// frame to act upon for reception - int frame_rx; - /// \brief Instance count for RXn-TXnp4 processing thread. - /// \internal This variable is protected by \ref mutex_rxtx. - int instance_cnt; - /// pthread structure for RXn-TXnp4 processing thread - pthread_t pthread; - /// pthread attributes for RXn-TXnp4 processing thread - pthread_attr_t attr; - /// condition variable for tx processing thread - pthread_cond_t cond; - /// mutex for RXn-TXnp4 processing thread - pthread_mutex_t mutex; - /// scheduling parameters for RXn-TXnp4 thread - struct sched_param sched_param_rxtx; +#include "PHY/TOOLS/time_meas.h" +#include "PHY/CODING/coding_defs.h" +#include "PHY/TOOLS/tools_defs.h" +#include "PHY/LTE_TRANSPORT/transport_eNB.h" - /// \internal This variable is protected by \ref mutex_RUs. - int instance_cnt_RUs; - /// condition variable for tx processing thread - pthread_cond_t cond_RUs; - /// mutex for RXn-TXnp4 processing thread - pthread_mutex_t mutex_RUs; -} L1_rxtx_proc_t; typedef struct { struct PHY_VARS_eNB_s *eNB; @@ -694,6 +664,57 @@ typedef struct PHY_VARS_eNB_s { int32_t pusch_stats_mcs[NUMBER_OF_UE_MAX][10240]; int32_t pusch_stats_bsr[NUMBER_OF_UE_MAX][10240]; int32_t pusch_stats_BO[NUMBER_OF_UE_MAX][10240]; + uint8_t *FS6bufferZone; } PHY_VARS_eNB; + +struct turboReqId { + uint16_t rnti; + uint16_t frame; + uint8_t subframe; + uint8_t codeblock; + uint16_t spare; +} __attribute__((packed)); + +union turboReqUnion { + struct turboReqId s; + uint64_t p; +}; + +typedef struct TurboDecode_s { + PHY_VARS_eNB *eNB; + decoder_if_t *function; + uint8_t decoded_bytes[3+1768] __attribute__((aligned(32))); + int UEid; + int harq_pid; + int frame; + int subframe; + int Fbits; + int Kr; + LTE_UL_eNB_HARQ_t *ulsch_harq; + int nbSegments; + int segment_r; + int r_offset; + int offset; + int maxIterations; + int decodeIterations; +} turboDecode_t; + +#define TURBO_SIMD_SOFTBITS 96+12+3+3*6144 +typedef struct turboEncode_s { + uint8_t * input; + int Kr_bytes; + int filler; + unsigned int G; + int r; + int harq_pid; + int round; + int r_offset; + LTE_eNB_DLSCH_t *dlsch; + time_stats_t *rm_stats; + time_stats_t *te_stats; + time_stats_t *i_stats; +} turboEncode_t; + + #endif /* __PHY_DEFS_ENB__H__ */ diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index 8105877bc3..96a073fbb8 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -596,7 +596,7 @@ void handle_uci_sr_pdu(PHY_VARS_eNB *eNB, uci->frame = frame; uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti; - uci->ue_id = find_dlsch(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); uci->type = SR; uci->pucch_fmt = pucch_format1; uci->num_antenna_ports = 1; @@ -622,7 +622,7 @@ void handle_uci_sr_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_ uci->frame = frame; uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti; - uci->ue_id = find_dlsch(ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); uci->type = HARQ_SR; uci->num_antenna_ports = 1; uci->num_pucch_resources = 1; @@ -644,7 +644,7 @@ void handle_uci_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu uci->frame = frame; uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti; - uci->ue_id = find_dlsch(ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + uci->ue_id = find_ulsch(ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); uci->type = HARQ; uci->srs_active = srs_active; uci->num_antenna_ports = ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel11.num_ant_ports; @@ -732,7 +732,7 @@ void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE) { AssertFatal(1==0,"NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE not handled yet\n"); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE) { - AssertFatal((UE_id = find_uci(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti, + AssertFatal((UE_id = find_uci(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti, proc->frame_tx,proc->subframe_tx,eNB,SEARCH_EXIST_OR_FREE))>=0, "No available UE UCI for rnti %x\n",ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti); handle_uci_sr_pdu(eNB,UE_id,ul_config_pdu,frame,subframe,srs_present); @@ -745,9 +745,8 @@ void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, } } -void schedule_response(Sched_Rsp_t *Sched_INFO) { +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc) { PHY_VARS_eNB *eNB; - L1_rxtx_proc_t *proc; // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; uint8_t CC_id = Sched_INFO->CC_id; @@ -767,7 +766,6 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { AssertFatal(RC.eNB[Mod_id][CC_id]!=NULL,"RC.eNB[%d][%d] is null\n",Mod_id,CC_id); eNB = RC.eNB[Mod_id][CC_id]; fp = &eNB->frame_parms; - proc = &eNB->proc.L1_proc; /* TODO: check that following line is correct - in the meantime it is disabled */ //if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)==SF_UL)) return; ul_subframe = pdcch_alloc2ul_subframe(fp,subframe); @@ -1020,11 +1018,11 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { /*Dummy functions*/ -int memcpy_dl_config_req (nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { +int memcpy_dl_config_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { return 0; } -int memcpy_ul_config_req (nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { +int memcpy_ul_config_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { return 0; } diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h index 05ec813917..4da1fa63ec 100644 --- a/openair1/SCHED/fapi_l1.h +++ b/openair1/SCHED/fapi_l1.h @@ -37,10 +37,10 @@ #include "SCHED/sched_common.h" #include "nfapi_interface.h" -void fill_uci_harq_indication(PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci,int frame,int subframe,uint8_t *harq_ack,uint8_t tdd_mapping_mode,uint16_t tdd_multiplexing_mask); +void fill_uci_harq_indication(int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci,int frame,int subframe,uint8_t *harq_ack,uint8_t tdd_mapping_mode,uint16_t tdd_multiplexing_mask); void fill_ulsch_harq_indication(PHY_VARS_eNB *eNB,LTE_UL_eNB_HARQ_t *ulsch_harq,uint16_t rnti, int frame,int subframe,int bundling); void fill_ulsch_cqi_indication(PHY_VARS_eNB *eNB,uint16_t frame,uint8_t subframe,LTE_UL_eNB_HARQ_t *ulsch_harq,uint16_t rnti); -void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat); +void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat); void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe); void fill_crc_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe,uint8_t crc_flag); void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc,nfapi_dl_config_request_pdu_t *dl_config_pdu); @@ -81,4 +81,4 @@ void handle_uci_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu void handle_srs_pdu(PHY_VARS_eNB *eNB,nfapi_ul_config_request_pdu_t *ul_config_pdu,uint16_t frame,uint8_t subframe); -void schedule_response(Sched_Rsp_t *Sched_INFO); +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 34d5a01590..ba03e79e62 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -47,6 +47,7 @@ #include #include "intertask_interface.h" +#include #define MBMS_NFAPI_SCHEDULER @@ -303,6 +304,7 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, start_meas(&eNB->dlsch_encoding_stats); dlsch_encoding_all(eNB, + proc, dlsch_harq->pdu, dlsch_harq->pdsch_start, dlsch, @@ -317,6 +319,14 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, &eNB->dlsch_interleaving_stats); stop_meas(&eNB->dlsch_encoding_stats); + if ( proc->threadPool->activated ) { + // Wait all other threads finish to process + while (proc->nbEncode) { + delNotifiedFIFO_elt(pullTpool(proc->respEncode, proc->threadPool)); + proc->nbEncode--; + } + } + if(eNB->dlsch_encoding_stats.p_time>500*3000 && opp_enabled == 1) { print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr); } @@ -431,6 +441,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here for (i=0; iulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; + else harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); @@ -591,7 +602,12 @@ void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } } -void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) { +void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) { + if ( split73 == SPLIT73_DU ) { + sendFs6Ulharq(fs6ULindicationSr, UEid, eNB, NULL, frame, subframe, NULL,0,0, rnti, stat); + return; + } + pthread_mutex_lock(&eNB->UL_INFO_mutex); nfapi_sr_indication_t *sr_ind = &eNB->UL_INFO.sr_ind; nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body; @@ -604,6 +620,7 @@ void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,u 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); pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; if (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0; @@ -640,6 +657,10 @@ uci_procedures(PHY_VARS_eNB *eNB, uci = &(eNB->uci_vars[i]); if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) { + if (uci->ue_id > MAX_MOBILES_PER_ENB) { + LOG_W(PHY, "UCI for UE %d and/or but is not active in MAC\n", uci->ue_id); + continue; + } LOG_D(PHY,"Frame %d, subframe %d: Running uci procedures (type %d) for %d \n", frame, subframe, @@ -710,7 +731,7 @@ uci_procedures(PHY_VARS_eNB *eNB, if (uci->type == SR) { if (SR_payload == 1) { - fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); + fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR); break; } else { break; @@ -744,7 +765,7 @@ uci_procedures(PHY_VARS_eNB *eNB, /* cancel SR detection if reception on n1_pucch0 is better than on SR PUCCH resource index, otherwise send it up to MAC */ if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0; - else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); + else if (SR_payload == 1) fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR); if (uci->type==HARQ_SR && metric[0] <= metric_SR) { /* when transmitting ACK/NACK on SR PUCCH resource index, SR payload is always 1 */ @@ -769,7 +790,7 @@ uci_procedures(PHY_VARS_eNB *eNB, frame,subframe, pucch_b0b1[0][0],metric[0]); uci->stat = metric[0]; - fill_uci_harq_indication(eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff); + fill_uci_harq_indication(i, eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff); } else { // frame_type == TDD LOG_D(PHY,"Frame %d Subframe %d Demodulating PUCCH (UCI %d) for ACK/NAK (uci->pucch_fmt %d,uci->type %d.uci->frame %d, uci->subframe %d): n1_pucch0 %d SR_payload %d\n", frame,subframe,i, @@ -791,7 +812,7 @@ uci_procedures(PHY_VARS_eNB *eNB, ); if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0; - else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); + else if (SR_payload == 1) fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR); if (uci->type==HARQ_SR && metric[0] <= metric_SR) { SR_payload = 1; @@ -873,7 +894,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = metric[0]; - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode } else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==2)) { // multiplexing + no SR, implement Table 10.1.3-5 (Rel14) for multiplexing with M=2 if (pucch_b0b1[0][0] == 4 || pucch_b0b1[1][0] == 4) { // there isn't a likely transmission @@ -909,7 +930,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = max(metric[0],metric[1]); - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode } //else if ((uci->tdd_bundling == 0) && (res==2)) else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==3)) { // multiplexing + no SR, implement Table 10.1.3-6 (Rel14) for multiplexing with M=3 if (harq_ack[0] == 4 || @@ -980,7 +1001,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = max_metric; - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode } } //else if ((uci->tdd_bundling == 0) && (res==3)) else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==4)) { // multiplexing + no SR, implement Table 10.1.3-7 (Rel14) for multiplexing with M=4 @@ -1102,14 +1123,14 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = max_metric; - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode } // else if ((uci->tdd_bundling == 0) && (res==4)) else { // bundling harq_ack[0] = pucch_b0b1[0][0]; harq_ack[1] = pucch_b0b1[0][1]; uci->stat = metric[0]; LOG_D(PHY,"bundling: (%d,%d), metric %d\n",harq_ack[0],harq_ack[1],uci->stat); - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,0,0xffff); // special_bundling mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,0,0xffff); // special_bundling mode } #ifdef DEBUG_PHY_PROC @@ -1140,8 +1161,93 @@ uci_procedures(PHY_VARS_eNB *eNB, } // end loop for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { } +void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { + turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); + + LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid]; + LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; + PHY_VARS_eNB *eNB=rdata->eNB; + + bool decodeSucess=rdata->decodeIterations <= rdata->maxIterations; + ulsch_harq->processedSegments++; + LOG_D(PHY, "processing result of segment: %d, ue %d, processed %d/%d\n", + rdata->segment_r, rdata->UEid, ulsch_harq->processedSegments, rdata->nbSegments); + proc->nbDecode--; + LOG_D(PHY,"remain to decoded in subframe: %d\n", proc->nbDecode); + if (decodeSucess) { + int Fbytes=(rdata->segment_r==0) ? rdata->Fbits>>3 : 0; + int sz=(rdata->Kr>>3) - Fbytes - ((ulsch_harq->C>1)?3:0); + memcpy(ulsch_harq->decodedBytes+rdata->offset, + rdata->decoded_bytes+Fbytes, + sz); + } else { + if ( rdata->nbSegments != ulsch_harq->processedSegments ) { + int nb=abortTpool(proc->threadPool, req->key); + nb+=abortNotifiedFIFO(proc->respDecode, req->key); + proc->nbDecode-=nb; + LOG_I(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); + AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", + ulsch_harq->processedSegments, nb, rdata->nbSegments); + ulsch_harq->processedSegments=rdata->nbSegments; + } + } + + // if this UE segments are all done + if ( rdata->nbSegments == ulsch_harq->processedSegments) { + //compute the expected ULSCH RX power (for the stats) + int i=rdata->UEid; + ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,rdata->harq_pid, 0); // 0 means bw_factor is not considered + if (RC.mac != NULL) { /* ulsim does not use RC.mac context. */ + if (ulsch_harq->cqi_crc_status == 1) { + fill_ulsch_cqi_indication(eNB,rdata->frame,rdata->subframe,ulsch_harq,ulsch->rnti); + RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << rdata->subframe)); + } else { + if(RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag & (1 << rdata->subframe) ) { + RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << rdata->subframe)); + RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_timer=30; + LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",rdata->frame,rdata->subframe); + } + } + } + + if (!decodeSucess) { + fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,1); // indicate NAK to MAC + fill_rx_indication(eNB,i,rdata->frame,rdata->subframe); // indicate SDU to MAC + LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", + eNB->Mod_id,rdata->harq_pid, + rdata->frame,rdata->subframe, i, + ulsch_harq->round, + ulsch->Mlimit, + ulsch_harq->o_ACK[0], + ulsch_harq->o_ACK[1]); + + if (ulsch_harq->round >= 3) { + ulsch_harq->status = SCH_IDLE; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + ulsch_harq->round = 0; + } + /* Mark the HARQ process to release it later if max transmission reached + * (see below). + * MAC does not send the max transmission count, we have to deal with it + * locally in PHY. + */ + ulsch_harq->handled = 1; + } // ulsch in error + else if(ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions){ + fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,0); // indicate ACK to MAC + fill_rx_indication(eNB,i,rdata->frame,rdata->subframe); // indicate SDU to MAC + ulsch_harq->status = SCH_IDLE; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + } // ulsch not in error + + if (ulsch_harq->O_ACK>0) + fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,rdata->frame,rdata->subframe,ulsch->bundling); + } +} + void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { - uint32_t ret=0,i; + uint32_t i; uint32_t harq_pid; uint8_t nPRS; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -1150,7 +1256,6 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); - int rvidx_tab[4] = {0,2,3,1}; for (i = 0; i < NUMBER_OF_UE_MAX; i++) { ulsch = eNB->ulsch[i]; @@ -1204,127 +1309,13 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { rx_ulsch(eNB,proc, i); stop_meas(&eNB->ulsch_demodulation_stats); start_meas(&eNB->ulsch_decoding_stats); - ret = ulsch_decoding(eNB,proc, + ulsch_decoding(eNB,proc, i, 0, // control_only_flag ulsch_harq->V_UL_DAI, ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); - LOG_D(PHY, - "[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d ulsch_harq->cqi_crc_status:%d ackBits:%d ulsch_decoding_stats[t:%lld max:%lld]\n", - eNB->Mod_id,harq_pid, - frame,subframe, - ulsch->rnti, - dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]), - dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]), - 30,//eNB->measurements.n0_power_dB[0], - 30,//eNB->measurements.n0_power_dB[1], - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1], - ret, - ulsch_harq->cqi_crc_status, - ulsch_harq->O_ACK, - eNB->ulsch_decoding_stats.p_time, eNB->ulsch_decoding_stats.max); - if (ulsch_harq->repetition_number < ulsch_harq->total_number_of_repetitions){ - ulsch_harq->rvidx = rvidx_tab[(ulsch_harq->repetition_number%4)] ; // Set the correct rvidx for the next emtc repetitions - ulsch_harq->repetition_number +=1 ; // Increment repetition_number for the next ULSCH allocation - } - //compute the expected ULSCH RX power (for the stats) - ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered - - if (RC.mac != NULL) { /* ulsim does not use RC.mac context. */ - if (ulsch_harq->cqi_crc_status == 1) { -#ifdef DEBUG_PHY_PROC - //if (((frame%10) == 0) || (frame < 50)) - print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL); -#endif - fill_ulsch_cqi_indication(eNB,frame,subframe,ulsch_harq,ulsch->rnti); - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); - } else { - if(RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag & (1 << subframe) ) { - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_timer=30; - LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",frame,subframe); - } - } - } - - if (ret == (1+MAX_TURBO_ITERATIONS)) { - T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti), - T_INT(harq_pid)); - fill_crc_indication(eNB,i,frame,subframe,1); // indicate NAK to MAC - fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC - LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", - eNB->Mod_id,harq_pid, - frame,subframe, i, - ulsch_harq->round, - ulsch->Mlimit, - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1]); - - if (ulsch_harq->round >= 3) { - ulsch_harq->status = SCH_IDLE; - ulsch_harq->handled = 0; - ulsch->harq_mask &= ~(1 << harq_pid); - ulsch_harq->round = 0; - } - - MSC_LOG_RX_DISCARDED_MESSAGE( - MSC_PHY_ENB,MSC_PHY_UE, - NULL,0, - "%05u:%02u ULSCH received rnti %x harq id %u round %d", - frame,subframe, - ulsch->rnti,harq_pid, - ulsch_harq->round-1 - ); - /* Mark the HARQ process to release it later if max transmission reached - * (see below). - * MAC does not send the max transmission count, we have to deal with it - * locally in PHY. - */ - ulsch_harq->handled = 1; - } // ulsch in error - else if(ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions){ - fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC - fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC - ulsch_harq->status = SCH_IDLE; - ulsch->harq_mask &= ~(1 << harq_pid); - T (T_ENB_PHY_ULSCH_UE_ACK, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (ulsch->rnti), T_INT (harq_pid)); - MSC_LOG_RX_MESSAGE( - MSC_PHY_ENB,MSC_PHY_UE, - NULL,0, - "%05u:%02u ULSCH received rnti %x harq id %u", - frame,subframe, - ulsch->rnti,harq_pid - ); -#ifdef DEBUG_PHY_PROC -#ifdef DEBUG_ULSCH - LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe, - harq_pid,ulsch_harq->TBS>>3); - - for (j=0; jTBS>>3; j++) - LOG_T(PHY,"%x.",ulsch->harq_processes[harq_pid]->b[j]); - - LOG_T(PHY,"\n"); -#endif -#endif - } // ulsch not in error - - if (ulsch_harq->O_ACK>0) fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,frame,subframe,ulsch->bundling); - - LOG_D(PHY,"[eNB %d] Frame %d subframe %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n", - eNB->Mod_id,frame,subframe, - harq_pid, - i, - ret, - ulsch_harq->cqi_crc_status, - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1], - eNB->UE_stats[i].ulsch_errors[harq_pid], - eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); - } // if ((ulsch) && - // (ulsch->rnti>0) && - // (ulsch_harq->status == ACTIVE)) + } else if ((ulsch) && (ulsch->rnti>0) && (ulsch_harq->status == ACTIVE) && @@ -1338,6 +1329,12 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); } } // for (i=0; inbDecode > 0) { + notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool); + postDecode(proc, req); + delNotifiedFIFO_elt(req); + } } extern int oai_exit; @@ -1345,24 +1342,29 @@ extern int oai_exit; extern void *td_thread (void *); void init_td_thread(PHY_VARS_eNB *eNB) { + /* L1_proc_t *proc = &eNB->proc; proc->tdp.eNB = eNB; proc->instance_cnt_td = -1; threadCreate(&proc->pthread_td, td_thread, (void *)&proc->tdp, "TD", -1, OAI_PRIORITY_RT); + */ } void kill_td_thread(PHY_VARS_eNB *eNB) { + /* L1_proc_t *proc = &eNB->proc; proc->instance_cnt_td = 0; pthread_cond_signal(&proc->cond_td); pthread_join(proc->pthread_td, NULL); pthread_mutex_destroy( &proc->mutex_td ); pthread_cond_destroy( &proc->cond_td ); + */ } extern void *te_thread (void *); void init_te_thread(PHY_VARS_eNB *eNB) { + /* L1_proc_t *proc = &eNB->proc; for(int i=0; i<3 ; i++) { @@ -1373,9 +1375,11 @@ void init_te_thread(PHY_VARS_eNB *eNB) { sprintf(txt,"TE_%d", i); threadCreate(&proc->tep[i].pthread_te, te_thread, (void *)&proc->tep[i], txt, -1, OAI_PRIORITY_RT); } + */ } void kill_te_thread(PHY_VARS_eNB *eNB) { + /* L1_proc_t *proc = &eNB->proc; for(int i=0; i<3 ; i++) { @@ -1385,6 +1389,7 @@ void kill_te_thread(PHY_VARS_eNB *eNB) { pthread_mutex_destroy( &proc->tep[i].mutex_te); pthread_cond_destroy( &proc->tep[i].cond_te); } + */ } void fill_rx_indication(PHY_VARS_eNB *eNB, @@ -1412,7 +1417,7 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation - pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->b; + pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->decodedBytes; // estimate timing advance for MAC sync_pos = lte_est_timing_advance_pusch(eNB,UE_id); timing_advance_update = sync_pos; // - eNB->frame_parms.nb_prefix_samples/4; //to check @@ -1745,7 +1750,12 @@ void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_har pthread_mutex_unlock(&eNB->UL_INFO_mutex); } -void fill_uci_harq_indication (PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { +void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { + if ( split73 == SPLIT73_DU ) { + sendFs6Ulharq(fs6ULindicationHarq, UEid, eNB, uci, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask, 0, 0); + return; + } + int UE_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST); //AssertFatal(UE_id>=0,"UE_id doesn't exist rnti:%x\n", uci->rnti); diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c index 6d392b0437..8846b77af9 100644 --- a/openair1/SCHED/ru_procedures.c +++ b/openair1/SCHED/ru_procedures.c @@ -321,7 +321,7 @@ void feptx_ofdm(RU_t *ru, fp->nb_prefix_samples, CYCLIC_PREFIX); } else { - if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)/*subframe==1*/){ + if(is_pmch_subframe(frame,subframe,fp)/*subframe==1*/){ normal_prefix_mod(&ru->common.txdataF_BF[aa][0], dummy_tx_b, 2, @@ -426,7 +426,7 @@ void feptx_ofdm(RU_t *ru, stop_meas(&ru->ofdm_mod_stats); LOG_D(PHY,"feptx_ofdm (TXPATH): frame %d, subframe %d: txp (time %p) %d dB, txp (freq) %d dB\n", - ru->proc.frame_tx,subframe,txdata,dB_fixed(signal_energy((int32_t*)txdata,fp->samples_per_tti)), + frame,subframe,txdata,dB_fixed(signal_energy((int32_t*)txdata,fp->samples_per_tti)), dB_fixed(signal_energy_nodc(ru->common.txdataF_BF[aa],2*slot_sizeF))); } } diff --git a/openair1/SCHED/sched_common.h b/openair1/SCHED/sched_common.h index e9af869b05..f3e43d516e 100644 --- a/openair1/SCHED/sched_common.h +++ b/openair1/SCHED/sched_common.h @@ -311,7 +311,7 @@ void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id); int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id, uint8_t eNB_index); -void schedule_response(Sched_Rsp_t *Sched_INFO); +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); diff --git a/openair1/SCHED/sched_eNB.h b/openair1/SCHED/sched_eNB.h index e74b9a312f..f04bec2e5c 100644 --- a/openair1/SCHED/sched_eNB.h +++ b/openair1/SCHED/sched_eNB.h @@ -128,8 +128,8 @@ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc); @param br_flag indicator for eMTC PRACH */ -void prach_procedures(PHY_VARS_eNB *eNB, - int br_flag); +void prach_procedures(PHY_VARS_eNB *eNB, + int br_flag); /*! \brief Function to compute timing of Msg3 transmission on UL-SCH (first UE transmission in RA procedure). This implements the timing in paragraph a) from Section 6.1.1 in 36.213 (p. 17 in version 8.6). Used by eNB upon transmission of random-access response (RA_RNTI) to program corresponding ULSCH reception procedure. Used by UE upon reception of random-access response (RA_RNTI) to program corresponding ULSCH transmission procedure. This does not support the UL_delay field in RAR (always assumed to be 0). @@ -193,7 +193,7 @@ int8_t find_ue_ulsch(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); -void schedule_response(Sched_Rsp_t *Sched_INFO); +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); LTE_eNB_UE_stats *get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); @@ -218,8 +218,6 @@ int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subf void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset); void release_rnti_of_phy(module_id_t mod_id); - -void ru_fep_full_2thread(RU_t *ru, int subframe); /*@}*/ diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index 7a423528ce..88ee2832cc 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -55,7 +55,7 @@ extern int oai_nfapi_nr_rach_ind(nfapi_rach_indication_t *rach_ind); void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_prach_pdu_t *prach_pdu) { - uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4]; + uint16_t max_preamble[4]={0},max_preamble_energy[4]={0},max_preamble_delay[4]={0}; uint16_t i; diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index fa22e43661..a36cebd6ae 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -202,7 +202,7 @@ int set_tdd_config_nr( nfapi_nr_config_request_scf_t *cfg, void add_tdd_dedicated_configuration_nr(NR_DL_FRAME_PARMS *frame_parms, int slotIndex, int nrofDownlinkSymbols, int nrofUplinkSymbols) { TDD_UL_DL_SlotConfig_t *p_TDD_UL_DL_ConfigDedicated = frame_parms->p_TDD_UL_DL_ConfigDedicated; - TDD_UL_DL_SlotConfig_t *p_previous_TDD_UL_DL_ConfigDedicated; + TDD_UL_DL_SlotConfig_t *p_previous_TDD_UL_DL_ConfigDedicated=NULL; int next = 0; while (p_TDD_UL_DL_ConfigDedicated != NULL) { diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr.h b/openair1/SCHED_NR_UE/phy_frame_config_nr.h index a939584584..a7e78397fe 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr.h +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr.h @@ -29,8 +29,8 @@ * ************************************************************************/ -#ifndef PHY_FRAME_CONFIG_NR_H -#define PHY_FRAME_CONFIG_NR_H +#ifndef PHY_FRAME_CONFIG_NR_UE_H +#define PHY_FRAME_CONFIG_NR_UE_H /************** DEFINE ********************************************/ diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index eb2ce3598f..1b4cbc2264 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -186,6 +186,8 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ int pucch_resource_id = MAX_NB_OF_PUCCH_RESOURCES; 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; /* update current context */ @@ -591,7 +593,9 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ case pucch_format2_nr: { nr_generate_pucch2(ue, - 0,//ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti, + crnti, + dmrs_scrambling_id, + data_scrambling_id, ue->common_vars.txdataF, &ue->frame_parms, &ue->pucch_config_dedicated[gNB_id], diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 6706b0f912..f65e1f9633 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -59,6 +59,7 @@ #include "unitary_defs.h" #include "dummy_functions.c" #include "executables/thread-common.h" +#include "executables/split_headers.h" void feptx_ofdm(RU_t *ru, int frame, int subframe); void feptx_prec(RU_t *ru, int frame, int subframe); @@ -78,6 +79,13 @@ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ int emulate_rf = 0; +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} void handler(int sig) { void *array[10]; @@ -515,7 +523,7 @@ int main(int argc, char **argv) { char fname[32],vname[32]; FILE *bler_fd; char bler_fname[256]; - FILE *time_meas_fd; + FILE *time_meas_fd=NULL; char time_meas_fname[256]; // FILE *tikz_fd; // char tikz_fname[256]; @@ -1266,6 +1274,13 @@ int main(int argc, char **argv) { } L1_rxtx_proc_t *proc_eNB = &eNB->proc.L1_proc; + proc_eNB->threadPool=(tpool_t*)malloc(sizeof(tpool_t)); + proc_eNB->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + proc_eNB->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initTpool("n", proc_eNB->threadPool, true); + initNotifiedFIFO(proc_eNB->respEncode); + initNotifiedFIFO(proc_eNB->respDecode); + proc_eNB->frame_tx=0; if (input_fd==NULL) { @@ -1446,7 +1461,7 @@ int main(int argc, char **argv) { sched_resp.subframe=subframe; sched_resp.frame=proc_eNB->frame_tx; eNB->abstraction_flag=0; - schedule_response(&sched_resp); + schedule_response(&sched_resp, proc_eNB); phy_procedures_eNB_TX(eNB,proc_eNB,1); if (uncoded_ber_bit == NULL) { @@ -1480,7 +1495,7 @@ int main(int argc, char **argv) { TX_req.tx_request_body.number_of_pdus=0; proc_eNB->subframe_tx = subframe+1; sched_resp.subframe=subframe+1; - schedule_response(&sched_resp); + schedule_response(&sched_resp, proc_eNB); phy_procedures_eNB_TX(eNB,proc_eNB,0); ru->proc.tti_tx=(subframe+1)%10; feptx_prec(ru,proc_eNB->frame_tx,subframe+1); @@ -1583,11 +1598,11 @@ int main(int argc, char **argv) { subframe<<1); for (i=0; idlsch[0][0]->harq_processes[0]->e[i]==1 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] > 0)|| - (eNB->dlsch[0][0]->harq_processes[0]->e[i]==0 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] < 0)) { + if ((eNB->dlsch[0][0]->harq_processes[0]->eDL[i]==1 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] > 0)|| + (eNB->dlsch[0][0]->harq_processes[0]->eDL[i]==0 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] < 0)) { uncoded_ber_bit[bit_errors++] = 1; printf("error in pos %d : %d => %d\n",i, - eNB->dlsch[0][0]->harq_processes[0]->e[i], + eNB->dlsch[0][0]->harq_processes[0]->eDL[i], UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i]); } else { /* @@ -1634,7 +1649,7 @@ int main(int argc, char **argv) { //pdsch_vars printf("coded_bits_per_codeword %u\n",coded_bits_per_codeword); dump_dlsch2(UE,eNB_id,subframe,&coded_bits_per_codeword,round, UE->dlsch[UE->current_thread_id[subframe]][0][0]->current_harq_pid); - LOG_M("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); + LOG_M("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->eDL,coded_bits_per_codeword,1,4); //pdcch_vars LOG_M("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[0][eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); LOG_M("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[0][eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index db97240ed5..c950d6f4da 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -54,6 +54,7 @@ #include "common/config/config_load_configmodule.h" #include "executables/thread-common.h" #include "targets/RT/USER/lte-softmodem.h" +#include "executables/split_headers.h" double cpuf; #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) @@ -81,6 +82,14 @@ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} + extern void fep_full(RU_t *ru, int subframe); extern void ru_fep_full_2thread(RU_t *ru, int subframe); //extern void eNB_fep_full(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); @@ -793,6 +802,13 @@ int main(int argc, char **argv) { proc_rxtx_ue->frame_rx = (subframe<4)?(proc_rxtx->frame_tx-1):(proc_rxtx->frame_tx); proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx; proc_rxtx_ue->subframe_rx = (proc_rxtx->subframe_tx+6)%10; + proc_rxtx->threadPool=(tpool_t*)malloc(sizeof(tpool_t)); + proc_rxtx->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + proc_rxtx->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initTpool("n",proc_rxtx->threadPool, true); + initNotifiedFIFO(proc_rxtx->respEncode); + initNotifiedFIFO(proc_rxtx->respDecode); + printf("Init UL hopping UE\n"); init_ul_hopping(&UE->frame_parms); printf("Init UL hopping eNB\n"); @@ -995,7 +1011,7 @@ int main(int argc, char **argv) { srs_flag); sched_resp.subframe=(subframe+6)%10; sched_resp.frame=(1024+eNB->proc.frame_rx+((subframe<4)?-1:0))&1023; - schedule_response(&sched_resp); + schedule_response(&sched_resp, proc_rxtx); ///////////////////// if (abstx) { @@ -1270,7 +1286,7 @@ int main(int argc, char **argv) { LOG_UDUMPMSG(SIM,dataArray(table_rx),table_rx->size,LOG_DUMP_DOUBLE,"The receiver raw data: \n"); } - printf("\n**********rb: %d ***mcs : %d *********SNR = %f dB (%f): TX %u dB (gain %f dB), N0W %f dB, I0 %d dB, delta_IF %d [ (%d,%d) dB / (%d,%d) dB ]**************************\n", + printf("\n**********rb: %d ***mcs : %d *********SNR = %f dB (%f): TX %u dB (gain %f dB), N0W %f dB, I0 %u dB, delta_IF %d [ (%d,%d) dB / (%u,%u) dB ]**************************\n", nb_rb,mcs,SNR,SNR2, tx_lev_dB, 20*log10(tx_gain), @@ -1352,7 +1368,7 @@ int main(int argc, char **argv) { printStatIndent2(&eNB->ulsch_deinterleaving_stats,"sub-block interleaving" ); printStatIndent2(&eNB->ulsch_demultiplexing_stats,"sub-block demultiplexing" ); printStatIndent2(&eNB->ulsch_rate_unmatching_stats,"sub-block rate-matching" ); - printf("|__ turbo_decoder(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n", + printf(" |__ turbo_decoder(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n", eNB->ulsch[0]->harq_processes[harq_pid]->Cminus ? eNB->ulsch[0]->harq_processes[harq_pid]->Kminus : eNB->ulsch[0]->harq_processes[harq_pid]->Kplus, diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 99ca466fee..9d14391f71 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -410,7 +410,7 @@ int main(int argc, char **argv) uint8_t n_hf = 0; int cyclic_prefix_type = NFAPI_CP_NORMAL; - double fs, eps; + double fs=0, eps; double scs = 30000; double bw = 100e6; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index aed7eb4505..10bdd23ef2 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -83,6 +83,7 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, cons int main(int argc, char **argv){ char c; + double sigma2, sigma2_dB = 0, SNR, snr0 = -2.0, snr1 = 0.0, ue_speed0 = 0.0, ue_speed1 = 0.0; double **s_re, **s_im, **r_re, **r_im, iqim = 0.0, delay_avg = 0, ue_speed = 0, fs, bw; int i, aa, aarx, **txdata, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1; @@ -92,12 +93,14 @@ int main(int argc, char **argv){ uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1; uint32_t tx_lev = 10000, prach_errors = 0, samp_count; //,tx_lev_dB; uint64_t SSB_positions = 0x01, absoluteFrequencyPointA = 640000; + // int8_t interf1=-19,interf2=-19; // uint8_t abstraction_flag=0,calibration_flag=0; // double prach_sinr; // uint32_t nsymb; // uint16_t preamble_max, preamble_energy_max; + NR_DL_FRAME_PARMS *frame_parms; NR_PRACH_RESOURCES_t prach_resources; nfapi_nr_prach_config_t *prach_config; diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 3b7305bf9b..d36f42f6c6 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -93,16 +93,18 @@ int main(int argc, char **argv) uint8_t nrofSymbols=1; //number of OFDM symbols can be 1-2 for format 1 uint8_t startingSymbolIndex=0; // resource allocated see 9.2.1, 38.213 for more info.should be actually present in the resource set provided uint16_t startingPRB=0,startingPRB_intraSlotHopping=0; //PRB number not sure see 9.2.1, 38.213 for more info. Should be actually present in the resource set provided + uint16_t nrofPRB=2; uint8_t timeDomainOCC=0; SCM_t channel_model=AWGN;//Rayleigh1_anticorr; int N_RB_DL=273,mu=1; - float target_error_rate=0.01; + float target_error_rate=0.001; int frame_length_complex_samples; //int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; //unsigned char frame_type = 0; int loglvl=OAILOG_WARNING; + int sr_flag = 0; cpuf = get_cpu_freq_GHz(); @@ -112,9 +114,8 @@ int main(int argc, char **argv) randominit(0); logInit(); - set_glog(loglvl); - while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL")) != -1) { + while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:c")) != -1) { switch (c) { case 'f': //write_output_file=1; @@ -263,6 +264,9 @@ int main(int argc, char **argv) case 'r': startingPRB=atoi(optarg); break; + case 'q': + nrofPRB=atoi(optarg); + break; case 'P': format=atoi(optarg); break; @@ -272,6 +276,9 @@ int main(int argc, char **argv) case 'b': nr_bit=atoi(optarg); break; + case 'c': + sr_flag=1; + break; case 'B': actual_payload=atoi(optarg); break; @@ -305,7 +312,8 @@ int main(int argc, char **argv) printf("-F Input filename (.txt format) for RX conformance testing\n"); printf("-i Enter number of ofdm symbols for pucch\n"); printf("-I Starting symbol index for pucch\n"); - printf("-r PUCCCH starting PRB\n"); + printf("-r PUCCH starting PRB\n"); + printf("-q PUCCH number of PRB\n"); printf("-P Enter the format of PUCCH\n"); printf("-b number of HARQ bits (1-2)\n"); printf("-B payload to be transmitted on PUCCH\n"); @@ -316,18 +324,22 @@ int main(int argc, char **argv) } } + set_glog(loglvl); + if (snr1set==0) snr1 = snr0+10; printf("Initializing gNodeB for mu %d, N_RB_DL %d\n",mu,N_RB_DL); - if((format!=0) && (format!=1)){ + if((format!=0) && (format!=1) && (format!=2)){ printf("PUCCH format %d not supported\n",format); exit(0); } - AssertFatal((nr_bit<3)&&(actual_payload<4),"Only format 0 and 1 currently supported. 2 bits max supported"); + AssertFatal(((format < 2)&&(nr_bit<3)&&(actual_payload<4)) || + ((format == 2)&&(nr_bit>2)&&(nr_bit<12)),"illegal combination format %d, nr_bit %d\n", + format,nr_bit); - if (nr_bit==1) actual_payload = actual_payload&1; + actual_payload &= ((1<ofdm_symbol_size); - txdataF[i] = malloc(14*frame_parms->ofdm_symbol_size*sizeof(int)); + txdataF[i] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int)); bzero(txdataF[i],14*frame_parms->ofdm_symbol_size*sizeof(int)); - rxdataF[i] = malloc(14*frame_parms->ofdm_symbol_size*sizeof(int)); + rxdataF[i] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int)); bzero(rxdataF[i],14*frame_parms->ofdm_symbol_size*sizeof(int)); } @@ -443,14 +455,17 @@ int main(int argc, char **argv) uint8_t mcs=0; startingPRB_intraSlotHopping=N_RB_DL-1; pucch_GroupHopping_t PUCCH_GroupHopping=UE->pucch_config_common_nr->pucch_GroupHopping; - uint32_t n_id=UE->pucch_config_common_nr->hoppingId; - + uint32_t hopping_id=UE->pucch_config_common_nr->hoppingId; + uint32_t dmrs_scrambling_id = 0, data_scrambling_id=0; if(format==0){ // for now we are not considering SR just HARQ-ACK - if(nr_bit==1) + if (nr_bit ==0) + mcs=table1_mcs[0]; + else if(nr_bit==1) mcs=table1_mcs[actual_payload]; else if(nr_bit==2) mcs=table2_mcs[actual_payload]; + else AssertFatal(1==0,"Either nr_bit %d or sr_flag %d must be non-zero\n"); } for(SNR=snr0;SNR<=snr1;SNR=SNR+1){ @@ -461,16 +476,20 @@ int main(int argc, char **argv) if(format==0){ nr_generate_pucch0(UE,txdataF,frame_parms,UE->pucch_config_dedicated,amp,nr_tti_tx,m0,mcs,nrofSymbols,startingSymbolIndex,startingPRB); } - else{ + else if (format == 1){ nr_generate_pucch1(UE,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,0,nr_bit); } + else { + nr_generate_pucch2(UE,0x1234,dmrs_scrambling_id,data_scrambling_id,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_tti_tx,nrofSymbols,startingSymbolIndex,nrofPRB,startingPRB,nr_bit); + } int txlev = signal_energy(&txdataF[aa][startingSymbolIndex*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size); // printf("txlev %d (%d dB), offset %d\n",txlev,dB_fixed(txlev),startingSymbolIndex*frame_parms->ofdm_symbol_size); - // note : this scaling is for 1 PRB, to be updated for PUCCH 2 - sigma2_dB = 10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/12)-SNR; + // note : this scaling + int nb_re = (format == 0 || format == 1)? 12 : 12*nrofPRB; + sigma2_dB = 10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/nb_re)-SNR; sigma2 = pow(10,sigma2_dB/10); for(i=startingSymbolIndex*frame_parms->ofdm_symbol_size; i<(startingSymbolIndex+1)*frame_parms->ofdm_symbol_size; i++) { @@ -487,9 +506,9 @@ int main(int argc, char **argv) pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping>>1)&1; pucch_pdu.bit_len_harq = nr_bit; - pucch_pdu.sr_flag = 0; + pucch_pdu.sr_flag = sr_flag; pucch_pdu.nr_of_symbols = nrofSymbols; - pucch_pdu.hopping_id = n_id; + pucch_pdu.hopping_id = hopping_id; pucch_pdu.initial_cyclic_shift = 0; pucch_pdu.start_symbol_index = startingSymbolIndex; pucch_pdu.prb_start = startingPRB; @@ -497,21 +516,49 @@ int main(int argc, char **argv) if(nr_bit==1) ack_nack_errors+=(actual_payload^uci_pdu.harq->harq_list[0].harq_value); else - ack_nack_errors+=((actual_payload^uci_pdu.harq->harq_list[0].harq_value)+((actual_payload>>1)^uci_pdu.harq->harq_list[1].harq_value)); + ack_nack_errors+=(((actual_payload&1)^uci_pdu.harq->harq_list[0].harq_value)+((actual_payload>>1)^uci_pdu.harq->harq_list[1].harq_value)); free(uci_pdu.harq->harq_list); } - else{ + else if (format==1) { - nr_decode_pucch1(rxdataF,PUCCH_GroupHopping,n_id,&(payload_received),frame_parms,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + nr_decode_pucch1(rxdataF,PUCCH_GroupHopping,hopping_id,&(payload_received),frame_parms,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); if(nr_bit==1) ack_nack_errors+=((actual_payload^payload_received)&1); else ack_nack_errors+=((actual_payload^payload_received)&1) + (((actual_payload^payload_received)&2)>>1); } + else if (format==2) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu; + nfapi_nr_pucch_pdu_t pucch_pdu; + pucch_pdu.rnti = 0x1234; + pucch_pdu.subcarrier_spacing = 1; + pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; + pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping>>1)&1; + pucch_pdu.bit_len_harq = nr_bit; + pucch_pdu.sr_flag = 0; + pucch_pdu.nr_of_symbols = nrofSymbols; + pucch_pdu.hopping_id = hopping_id; + pucch_pdu.initial_cyclic_shift = 0; + pucch_pdu.start_symbol_index = startingSymbolIndex; + pucch_pdu.prb_size = nrofPRB; + pucch_pdu.prb_start = startingPRB; + pucch_pdu.dmrs_scrambling_id = dmrs_scrambling_id; + pucch_pdu.data_scrambling_id = data_scrambling_id; + nr_decode_pucch2(gNB,nr_tti_tx,&uci_pdu,&pucch_pdu); + int harq_bytes=pucch_pdu.bit_len_harq>>3; + if ((pucch_pdu.bit_len_harq&7) > 0) harq_bytes++; + for (int i=0;i>1)+(((actual_payload^payload_received)&4)>>2)+n_errors; } printf("SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors); - if((float)ack_nack_errors/(float)(nr_bit*n_trials)<=target_error_rate){ + if((float)ack_nack_errors/(float)(n_trials)<=target_error_rate){ printf("PUCCH test OK\n"); break; } diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 3fced2c83d..840eaa9ffe 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -109,7 +109,7 @@ openair0_config_t openair0_cfg[MAX_CARDS]; int main(int argc, char **argv) { char c; - int i,sf; + int i; double SNR, snr0 = -2.0, snr1 = 2.0; double sigma, sigma_dB; double snr_step = 1; @@ -426,7 +426,7 @@ int main(int argc, char **argv) for (i = 0; i < RC.nb_nr_macrlc_inst; i++) RC.nb_nr_mac_CC[i] = 1; mac_top_init_gNB(); - gNB_MAC_INST* gNB_mac = RC.nrmac[0]; + //gNB_MAC_INST* gNB_mac = RC.nrmac[0]; gNB_RRC_INST rrc; memset((void*)&rrc,0,sizeof(rrc)); @@ -487,7 +487,7 @@ int main(int argc, char **argv) init_nr_ue_transport(UE, 0); /* - for (sf = 0; sf < 2; sf++) { + for (int sf = 0; sf < 2; sf++) { for (i = 0; i < 2; i++) { UE->ulsch[sf][0][i] = new_nr_ue_ulsch(N_RB_UL, 8, 0); diff --git a/openair2/COMMON/platform_constants.h b/openair2/COMMON/platform_constants.h index f15751fbee..77f7e26c67 100644 --- a/openair2/COMMON/platform_constants.h +++ b/openair2/COMMON/platform_constants.h @@ -73,7 +73,9 @@ #ifdef UESIM_EXPANSION #define MAX_MOBILES_PER_ENB 256 #define MAX_MOBILES_PER_ENB_NB_IoT 256 + #define MAX_MOBILES_PER_GNB 256 #define MAX_eNB 2 + #define MAX_gNB 2 #else #ifdef LARGE_SCALE #define MAX_MOBILES_PER_ENB 128 diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index 1d0c2dfdb8..cde2497880 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -76,3 +76,6 @@ MESSAGE_DEF(NAS_DOWNLINK_DATA_IND, MESSAGE_PRIORITY_MED, NasDlDataInd // eNB: realtime -> RRC messages MESSAGE_DEF(RRC_SUBFRAME_PROCESS, MESSAGE_PRIORITY_MED, RrcSubframeProcess, rrc_subframe_process) + +// eNB: RLC -> RRC messages +MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 68e1753448..7582de65ba 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -87,6 +87,8 @@ #define RRC_SUBFRAME_PROCESS(mSGpTR) (mSGpTR)->ittiMsg.rrc_subframe_process +#define RLC_SDU_INDICATION(mSGpTR) (mSGpTR)->ittiMsg.rlc_sdu_indication + //-------------------------------------------------------------------------------------------// typedef struct RrcStateInd_s { Rrc_State_t state; @@ -429,4 +431,12 @@ typedef struct rrc_subframe_process_s { int CC_id; } RrcSubframeProcess; +// eNB: RLC -> RRC messages +typedef struct rlc_sdu_indication_s { + int rnti; + int is_successful; + int srb_id; + int message_id; +} RlcSduIndication; + #endif /* RRC_MESSAGES_TYPES_H_ */ diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index c489f10dae..975ac4e96f 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -939,7 +939,7 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { for (j = 0; j < 8; j++) { - if (RC.mac && RC.mac[mod_id] && RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid == 1) { + if (RC.mac && RC.mac[mod_id] && RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid == 1) { available_harq[i] = j; break; } @@ -977,13 +977,13 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle dl_info[i]->harq_process_id = available_harq[UE_id]; if (RC.mac && RC.mac[mod_id]) - RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id, UE_id)][UE_id].harq_pid = 0; + RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id, UE_id)][UE_id].harq_pid = 0; dl_info[i]->has_harq_process_id = 1; /* Fill in the status of the HARQ process (2 TBs)*/ dl_info[i]->n_harq_status = 2; dl_info[i]->harq_status = malloc(sizeof(uint32_t) * dl_info[i]->n_harq_status); for (j = 0; j < dl_info[i]->n_harq_status; j++) { - dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_list.UE_sched_ctrl[UE_id].round[UE_PCCID(mod_id, UE_id)][j]; + dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_info.UE_sched_ctrl[UE_id].round[UE_PCCID(mod_id, UE_id)][j]; // TODO: This should be different per TB } // LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d and harq %d (round %d)\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10, dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]); @@ -1357,7 +1357,7 @@ void flexran_agent_init_mac_agent(mid_t mod_id) { for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { for (j = 0; j < 8; j++) { if (RC.mac && RC.mac[mod_id]) - RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0; + RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0; } } } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index 30c10940c9..a85cbac543 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -290,7 +290,7 @@ Protocol__FlexUlCqiReport * copy_ul_cqi_report(Protocol__FlexUlCqiReport * origi full_ul_report->has_sfn_sn = original->has_sfn_sn; full_ul_report->n_cqi_meas = original->n_cqi_meas; - Protocol__FlexUlCqi **ul_report; + Protocol__FlexUlCqi **ul_report=NULL; ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas); if(ul_report == NULL) goto error; @@ -348,7 +348,7 @@ Protocol__FlexDlCqiReport * copy_dl_cqi_report(Protocol__FlexDlCqiReport * origi dl_report->has_sfn_sn = original->has_sfn_sn; dl_report->n_csi_report = original->n_csi_report; - Protocol__FlexDlCsi **csi_reports; + Protocol__FlexDlCsi **csi_reports=NULL; csi_reports = malloc(sizeof(Protocol__FlexDlCsi *) * dl_report->n_csi_report); if (csi_reports == NULL) goto error; @@ -383,7 +383,7 @@ Protocol__FlexPagingBufferReport * copy_paging_buffer_report(Protocol__FlexPagin protocol__flex_paging_buffer_report__init(copy); copy->n_paging_info = original->n_paging_info; - Protocol__FlexPagingInfo **p_info; + Protocol__FlexPagingInfo **p_info=NULL; p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * copy->n_paging_info); if (p_info == NULL) goto error; diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index f91c7056c5..344214a1f1 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -90,6 +90,7 @@ typedef enum { #define CONFIG_STRING_RU_NBIOTRRC_LIST "NbIoT_RRC_instances" #define CONFIG_STRING_RU_SDR_ADDRS "sdr_addrs" #define CONFIG_STRING_RU_SDR_CLK_SRC "clock_src" +#define CONFIG_STRING_RU_SDR_TME_SRC "time_src" #define CONFIG_STRING_RU_SF_EXTENSION "sf_extension" #define CONFIG_STRING_RU_END_OF_BURST_DELAY "end_of_burst_delay" #define CONFIG_STRING_RU_OTA_SYNC_ENABLE "ota_sync_enabled" @@ -117,11 +118,12 @@ typedef enum { #define RU_NBIOTRRC_LIST_IDX 18 #define RU_SDR_ADDRS 19 #define RU_SDR_CLK_SRC 20 -#define RU_SF_EXTENSION_IDX 21 -#define RU_END_OF_BURST_DELAY_IDX 22 -#define RU_OTA_SYNC_ENABLE_IDX 23 -#define RU_BF_WEIGHTS_LIST_IDX 24 -#define RU_IF_FREQUENCY 25 +#define RU_SDR_TME_SRC 21 +#define RU_SF_EXTENSION_IDX 22 +#define RU_END_OF_BURST_DELAY_IDX 23 +#define RU_OTA_SYNC_ENABLE_IDX 24 +#define RU_BF_WEIGHTS_LIST_IDX 25 +#define RU_IF_FREQUENCY 26 /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* RU configuration parameters */ @@ -149,6 +151,7 @@ typedef enum { {CONFIG_STRING_RU_NBIOTRRC_LIST, NULL, 0, uptr:NULL, defintarrayval:DEFENBS, TYPE_INTARRAY, 1}, \ {CONFIG_STRING_RU_SDR_ADDRS, NULL, 0, strptr:NULL, defstrval:"type=b200", TYPE_STRING, 0}, \ {CONFIG_STRING_RU_SDR_CLK_SRC, NULL, 0, strptr:NULL, defstrval:"internal", TYPE_STRING, 0}, \ + {CONFIG_STRING_RU_SDR_TME_SRC, NULL, 0, strptr:NULL, defstrval:"internal", TYPE_STRING, 0}, \ {CONFIG_STRING_RU_SF_EXTENSION, NULL, 0, uptr:NULL, defuintval:312, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_END_OF_BURST_DELAY, NULL, 0, uptr:NULL, defuintval:400, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_OTA_SYNC_ENABLE, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index a66081d99f..32cb8c74e1 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -98,7 +98,7 @@ uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time) { int flexran_get_mac_num_ues(mid_t mod_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.num_UEs; + return RC.mac[mod_id]->UE_info.num_UEs; } int flexran_get_num_ue_lcs(mid_t mod_id, mid_t ue_id) { @@ -123,7 +123,7 @@ int flexran_get_mac_ue_id_rnti(mid_t mod_id, rnti_t rnti) { /* get the (active) UE with RNTI i */ for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[mod_id]->UE_list.active[n] == TRUE + if (RC.mac[mod_id]->UE_info.active[n] == TRUE && rnti == UE_RNTI(mod_id, n)) { return n; } @@ -139,7 +139,7 @@ int flexran_get_mac_ue_id(mid_t mod_id, int i) { /* get the (i+1)'th active UE */ for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[mod_id]->UE_list.active[n] == TRUE) { + if (RC.mac[mod_id]->UE_info.active[n] == TRUE) { if (i == 0) return n; @@ -159,19 +159,19 @@ rnti_t flexran_get_mac_ue_crnti(mid_t mod_id, mid_t ue_id) { int flexran_get_ue_bsr_ul_buffer_info(mid_t mod_id, mid_t ue_id, lcid_t lcid) { if (!mac_is_present(mod_id)) return -1; - return RC.mac[mod_id]->UE_list.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].ul_buffer_info[lcid]; + return RC.mac[mod_id]->UE_info.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].ul_buffer_info[lcid]; } int8_t flexran_get_ue_phr(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].phr_info; + return RC.mac[mod_id]->UE_info.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].phr_info; } uint8_t flexran_get_ue_wcqi(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].dl_cqi[0]; + return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].dl_cqi[0]; } rlc_buffer_occupancy_t flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) { @@ -180,7 +180,7 @@ rlc_buffer_occupancy_t flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logi rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id); frame_t frame = flexran_get_current_frame(mod_id); sub_frame_t subframe = flexran_get_current_subframe(mod_id); - mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0,0, 0 + mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0, 0 ); return rlc_status.bytes_in_buffer; } @@ -191,7 +191,7 @@ rlc_buffer_occupancy_t flexran_get_num_pdus_buffer(mid_t mod_id, mid_t ue_id, lo rnti_t rnti = flexran_get_mac_ue_crnti(mod_id,ue_id); frame_t frame = flexran_get_current_frame(mod_id); sub_frame_t subframe = flexran_get_current_subframe(mod_id); - mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0,0, 0 + mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0, 0 ); return rlc_status.pdus_in_buffer; } @@ -202,7 +202,7 @@ frame_t flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t chann rnti_t rnti = flexran_get_mac_ue_crnti(mod_id,ue_id); frame_t frame = flexran_get_current_frame(mod_id); sub_frame_t subframe = flexran_get_current_subframe(mod_id); - mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0,0, 0 + mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0, 0 ); return rlc_status.head_sdu_creation_time; } @@ -242,7 +242,7 @@ int32_t flexran_get_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { uint32_t flexran_get_total_size_dl_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_sdu_bytes; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_sdu_bytes; } uint32_t flexran_get_total_size_ul_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id) { @@ -251,7 +251,7 @@ uint32_t flexran_get_total_size_ul_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id uint64_t bytes = 0; for (int i = 0; i < NB_RB_MAX; ++i) { - bytes += RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].num_bytes_rx[i]; + bytes += RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].num_bytes_rx[i]; } return bytes; @@ -260,135 +260,135 @@ uint32_t flexran_get_total_size_ul_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id uint32_t flexran_get_TBS_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].TBS; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].TBS; } uint32_t flexran_get_TBS_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].ulsch_TBS; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].ulsch_TBS; } uint16_t flexran_get_num_prb_retx_dl_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used_retx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used_retx; } uint32_t flexran_get_num_prb_retx_ul_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used_retx_rx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used_retx_rx; } uint16_t flexran_get_num_prb_dl_tx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used; } uint16_t flexran_get_num_prb_ul_rx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used_rx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used_rx; } uint8_t flexran_get_ue_wpmi(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].periodic_wideband_pmi[cc_id]; + return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].periodic_wideband_pmi[cc_id]; } uint8_t flexran_get_mcs1_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].dlsch_mcs1; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].dlsch_mcs1; } uint8_t flexran_get_mcs2_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].dlsch_mcs2; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].dlsch_mcs2; } uint8_t flexran_get_mcs1_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].ulsch_mcs1; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].ulsch_mcs1; } uint8_t flexran_get_mcs2_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].ulsch_mcs2; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].ulsch_mcs2; } uint32_t flexran_get_total_prb_dl_tx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_rbs_used; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_rbs_used; } uint32_t flexran_get_total_prb_ul_rx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_rbs_used_rx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_rbs_used_rx; } uint32_t flexran_get_total_num_pdu_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_num_pdus; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_num_pdus; } uint32_t flexran_get_total_num_pdu_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_num_pdus_rx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_num_pdus_rx; } uint64_t flexran_get_total_TBS_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_pdu_bytes; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_pdu_bytes; } uint64_t flexran_get_total_TBS_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_ulsch_TBS; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_ulsch_TBS; } int flexran_get_harq_round(mid_t mod_id, uint8_t cc_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].harq_round; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].harq_round; } uint32_t flexran_get_num_mac_sdu_tx(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].num_mac_sdu_tx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].num_mac_sdu_tx; } unsigned char flexran_get_mac_sdu_lcid_index(mid_t mod_id, mid_t ue_id, int cc_id, int index) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].lcid_sdu[index]; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].lcid_sdu[index]; } uint32_t flexran_get_mac_sdu_size(mid_t mod_id, mid_t ue_id, int cc_id, int lcid) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].sdu_length_tx[lcid]; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].sdu_length_tx[lcid]; } /* TODO needs to be revised */ void flexran_update_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { /* - UE_list_t *UE_list=&eNB_mac_inst[mod_id].UE_list; - UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id]; + UE_info_t *UE_info=&eNB_mac_inst[mod_id].UE_info; + UE_sched_ctrl *ue_sched_ctl = &UE_info->UE_sched_ctrl[ue_id]; if (ue_sched_ctl->ta_timer == 0) { @@ -432,7 +432,7 @@ int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { int flexran_get_active_CC(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.numactiveCCs[ue_id]; + return RC.mac[mod_id]->UE_info.numactiveCCs[ue_id]; } uint8_t flexran_get_current_RI(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { @@ -890,13 +890,13 @@ uint8_t flexran_get_rrc_status(mid_t mod_id, rnti_t rnti) { uint64_t flexran_get_ue_aggregated_max_bitrate_dl(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL; + return 0; //RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL; } uint64_t flexran_get_ue_aggregated_max_bitrate_ul(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL; + return 0; //RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL; } int flexran_get_half_duplex(mid_t mod_id, rnti_t rnti) { @@ -1235,7 +1235,7 @@ uint64_t flexran_get_ue_imsi(mid_t mod_id, rnti_t rnti) { long flexran_get_lcg(mid_t mod_id, mid_t ue_id, mid_t lc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].lcgidmap[lc_id]; + return RC.mac[mod_id]->UE_info.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].lcgidmap[lc_id]; } /* TODO Navid: needs to be revised */ @@ -3016,7 +3016,7 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti) int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - int slice_idx = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id]; + int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id]; if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl) return RC.mac[mod_id]->slice_info.dl[slice_idx].id; @@ -3031,13 +3031,13 @@ void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!flexran_dl_slice_exists(mod_id, slice_idx)) return; - RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id] = slice_idx; + //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id] = slice_idx; } int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - int slice_idx = RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[ue_id]; + int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id]; if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul) return RC.mac[mod_id]->slice_info.ul[slice_idx].id; @@ -3052,7 +3052,7 @@ void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!flexran_ul_slice_exists(mod_id, slice_idx)) return; - RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[ue_id] = slice_idx; + //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx; } int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) { @@ -3103,14 +3103,14 @@ int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl])); /* all UEs that have been in the old slice are put into slice index 0 */ - int *assoc_list = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx; + //int *assoc_list = RC.mac[mod_id]->UE_info.assoc_dl_slice_idx; - for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { - if (assoc_list[i] == slice_idx) - assoc_list[i] = 0; - } + //for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { + // if (assoc_list[i] == slice_idx) + // assoc_list[i] = 0; + //} - return sli->n_dl; + return 1; } int flexran_get_num_dl_slices(mid_t mod_id) { @@ -3397,12 +3397,12 @@ int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul])); /* all UEs that have been in the old slice are put into slice index 0 */ - int *assoc_list = RC.mac[mod_id]->UE_list.assoc_ul_slice_idx; + //int *assoc_list = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx; - for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { - if (assoc_list[i] == slice_idx) - assoc_list[i] = 0; - } + //for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { + // if (assoc_list[i] == slice_idx) + // assoc_list[i] = 0; + //} return sli->n_ul; } diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index edc5a2c0a9..a64f2d529b 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -37,7 +37,6 @@ #include "f1ap_cu_ue_context_management.h" #include -#include "openair2/LAYER2/MAC/mac_proto.h" #include "rrc_extern.h" #include "rrc_eNB_UE_context.h" #include "rrc_eNB_S1AP.h" diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 803551818a..fb9450728b 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -697,7 +697,7 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, break; } - UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[instance]->UE_list.UE_sched_ctrl[UE_id_mac]); + UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[instance]->UE_info.UE_sched_ctrl[UE_id_mac]); if (UE_scheduling_control->cdrx_waiting_ack == TRUE) { UE_scheduling_control->cdrx_waiting_ack = FALSE; diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index b9c79e1f18..bae59a509e 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -633,9 +633,9 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, int UE_out_of_sync = 0; for (int n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[instance]->UE_list.active[n] == TRUE + if (RC.mac[instance]->UE_info.active[n] == TRUE && rnti == UE_RNTI(instance, n)) { - UE_out_of_sync = RC.mac[instance]->UE_list.UE_sched_ctrl[n].ul_out_of_sync; + UE_out_of_sync = RC.mac[instance]->UE_info.UE_sched_ctrl[n].ul_out_of_sync; break; } } diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 69c971fb1d..3235dabb45 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -987,8 +987,6 @@ void NRRCConfig(void) { paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; paramdef_t GNBSParams[] = GNBSPARAMS_DESC; - char aprefix[MAX_OPTNAME_SIZE*2 + 8]; - /* get global parameters, defined outside any section in the config file */ LOG_I(GNB_APP, "Getting GNBSParams\n"); diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 76c8e33b16..49949bd771 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -782,7 +782,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, int i; int UE_id = -1; eNB_MAC_INST *eNB = RC.mac[Mod_idP]; - UE_list_t *UE_list= &eNB->UE_list; + UE_info_t *UE_info= &eNB->UE_info; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_IN); LOG_D(MAC, "RC.mac:%p mib:%p\n", RC.mac, mib); @@ -882,6 +882,34 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, } } + if (logicalChannelIdentity > 0) { // is SRB1,2 or DRB + if ((UE_id = find_UE_id(Mod_idP, rntiP)) < 0) { + LOG_E(MAC,"Configuration received for unknown UE (%x), shouldn't happen\n",rntiP); + return(-1); + } + int idx = -1; + UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) { + if (sched_ctrl->dl_lc_ids[i] == logicalChannelIdentity) { + /* TODO this might also mean we have to remove it, not clear */ + idx = i; + break; + } + } + if (idx < 0) { + sched_ctrl->dl_lc_num++; + sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num-1] = logicalChannelIdentity; + sched_ctrl->dl_lc_bytes[sched_ctrl->dl_lc_num-1] = 0; + LOG_I(MAC, "UE %d RNTI %x adding LC %ld idx %d to scheduling control (total %d)\n", UE_id, rntiP, logicalChannelIdentity, sched_ctrl->dl_lc_num-1, sched_ctrl->dl_lc_num); + if (logicalChannelIdentity == 1) { // if it is SRB1, add SRB2 directly because RRC does not indicate this separately + sched_ctrl->dl_lc_num++; + sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num-1] = 2; + sched_ctrl->dl_lc_bytes[sched_ctrl->dl_lc_num-1] = 0; + LOG_I(MAC, "UE %d RNTI %x adding LC 2 idx %d to scheduling control (total %d)\n", UE_id, rntiP, sched_ctrl->dl_lc_num-1, sched_ctrl->dl_lc_num); + } + } + } + // SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup if (logicalChannelConfig != NULL) { // check for eMTC specific things UE_id = find_UE_id(Mod_idP, rntiP); @@ -892,9 +920,9 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, } if (logicalChannelConfig) { - UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = *logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup; - UE_list->UE_template[CC_idP][UE_id].lcgidpriority[logicalChannelIdentity] = logicalChannelConfig->ul_SpecificParameters->priority; - } else UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = 0; + UE_info->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = *logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup; + UE_info->UE_template[CC_idP][UE_id].lcgidpriority[logicalChannelIdentity] = logicalChannelConfig->ul_SpecificParameters->priority; + } else UE_info->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = 0; } if (physicalConfigDedicated != NULL) { @@ -905,7 +933,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, return(-1); } - UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated = physicalConfigDedicated; + UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated = physicalConfigDedicated; LOG_I(MAC,"Added physicalConfigDedicated %p for %d.%d\n",physicalConfigDedicated,CC_idP,UE_id); } @@ -1048,15 +1076,11 @@ void eNB_Config_Local_DRX(instance_t Mod_id, rrc_mac_drx_config_req_t *rrc_mac_drx_config_req) //----------------------------------------------------------------------------- { - UE_list_t *UE_list_mac = NULL; + UE_info_t *UE_info_mac = &RC.mac[Mod_id]->UE_info; UE_sched_ctrl_t *UE_scheduling_control = NULL; - int UE_id = -1; - - rnti_t rnti = rrc_mac_drx_config_req->rnti; LTE_DRX_Config_t *const drx_Configuration = rrc_mac_drx_config_req->drx_Configuration; - - UE_list_mac = &(RC.mac[Mod_id]->UE_list); - UE_id = find_UE_id(Mod_id, rnti); + rnti_t rnti = rrc_mac_drx_config_req->rnti; + int UE_id = find_UE_id(Mod_id, rnti); /* Check UE_id */ if (UE_id == -1) { @@ -1065,7 +1089,7 @@ void eNB_Config_Local_DRX(instance_t Mod_id, } /* Get struct to modify */ - UE_scheduling_control = &(UE_list_mac->UE_sched_ctrl[UE_id]); + UE_scheduling_control = &(UE_info_mac->UE_sched_ctrl[UE_id]); UE_scheduling_control->cdrx_configured = FALSE; // will be set to true when no error /* Check drx_Configuration */ diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h deleted file mode 100644 index 05660b727e..0000000000 --- a/openair2/LAYER2/MAC/defs.h +++ /dev/null @@ -1,1321 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file LAYER2/MAC/defs.h -* \brief MAC data structures, constant, and function prototype -* \author Navid Nikaein and Raymond Knopp -* \date 2011 -* \version 0.5 -* \email navid.nikaein@eurecom.fr - -*/ -/** @defgroup _oai2 openair2 Reference Implementation - * @ingroup _ref_implementation_ - * @{ - */ - -/*@}*/ - -#ifndef __LAYER2_MAC_DEFS_H__ -#define __LAYER2_MAC_DEFS_H__ - - - -#ifdef USER_MODE - #include - #include - #include -#endif - -//#include "COMMON/openair_defs.h" - - - -#include "PHY/defs.h" -#include "PHY/LTE_TRANSPORT/defs.h" -#include "COMMON/platform_constants.h" -#include "BCCH-BCH-Message.h" -#include "RadioResourceConfigCommon.h" -#include "RadioResourceConfigDedicated.h" -#include "MeasGapConfig.h" -#include "SchedulingInfoList.h" -#include "TDD-Config.h" -#include "RACH-ConfigCommon.h" -#include "MeasObjectToAddModList.h" -#include "MobilityControlInfo.h" -#include "MBSFN-AreaInfoList-r9.h" -#include "MBSFN-SubframeConfigList.h" -#include "PMCH-InfoList-r9.h" -#include "SCellToAddMod-r10.h" -#include "SystemInformationBlockType1-v1310-IEs.h" - - -#include "nfapi_interface.h" -#include "PHY_INTERFACE/IF_Module.h" - -/** @defgroup _mac MAC - * @ingroup _oai2 - * @{ - */ - -#define BCCH_PAYLOAD_SIZE_MAX 128 -#define CCCH_PAYLOAD_SIZE_MAX 128 -#define PCCH_PAYLOAD_SIZE_MAX 128 -#define RAR_PAYLOAD_SIZE_MAX 128 - -#define SCH_PAYLOAD_SIZE_MAX 4096 -/// Logical channel ids from 36-311 (Note BCCH is not specified in 36-311, uses the same as first DRB) - - -// Mask for identifying subframe for MBMS -#define MBSFN_TDD_SF3 0x80// for TDD -#define MBSFN_TDD_SF4 0x40 -#define MBSFN_TDD_SF7 0x20 -#define MBSFN_TDD_SF8 0x10 -#define MBSFN_TDD_SF9 0x08 -#define MBSFN_FDD_SF1 0x80// for FDD -#define MBSFN_FDD_SF2 0x40 -#define MBSFN_FDD_SF3 0x20 -#define MBSFN_FDD_SF6 0x10 -#define MBSFN_FDD_SF7 0x08 -#define MBSFN_FDD_SF8 0x04 - -#define MAX_MBSFN_AREA 8 -#define MAX_PMCH_perMBSFN 15 -/*!\brief MAX MCCH payload size */ -#define MCCH_PAYLOAD_SIZE_MAX 128 - - -#ifdef USER_MODE - #define printk printf -#endif //USER_MODE - -/*!\brief Maximum number of logical channl group IDs */ -#define MAX_NUM_LCGID 4 -/*!\brief logical channl group ID 0 */ -#define LCGID0 0 -/*!\brief logical channl group ID 1 */ -#define LCGID1 1 -/*!\brief logical channl group ID 2 */ -#define LCGID2 2 -/*!\brief logical channl group ID 3 */ -#define LCGID3 3 -/*!\brief Maximum number of logical chanels */ -#define MAX_NUM_LCID 11 -/*!\brief Maximum number od control elemenets */ -#define MAX_NUM_CE 5 -/*!\brief Maximum number of random access process */ -#define NB_RA_PROC_MAX 4 -/*!\brief size of buffer status report table */ -#define BSR_TABLE_SIZE 64 -/*!\brief The power headroom reporting range is from -23 ...+40 dB and beyond, with step 1 */ -#define PHR_MAPPING_OFFSET 23 // if ( x>= -23 ) val = floor (x + 23) -/*!\brief maximum number of resource block groups */ -#define N_RBG_MAX 25 // for 20MHz channel BW -/*!\brief minimum value for channel quality indicator */ -#define MIN_CQI_VALUE 0 -/*!\brief maximum value for channel quality indicator */ -#define MAX_CQI_VALUE 15 -/*!\briefmaximum number of supported bandwidth (1.4, 5, 10, 20 MHz) */ -#define MAX_SUPPORTED_BW 4 -/*!\brief CQI values range from 1 to 15 (4 bits) */ -#define CQI_VALUE_RANGE 16 - -/*!\brief value for indicating BSR Timer is not running */ -#define MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) - -#define LCID_EMPTY 0 -#define LCID_NOT_EMPTY 1 - -/*!\brief minimum RLC PDU size to be transmitted = min RLC Status PDU or RLC UM PDU SN 5 bits */ -#define MIN_RLC_PDU_SIZE (2) - -/*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */ -#define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE) - -/*!\brief maximum number of slices / groups */ -#define MAX_NUM_SLICES 4 - -/* - * eNB part - */ - - -/* - * UE/ENB common part - */ -/*!\brief MAC header of Random Access Response for Random access preamble identifier (RAPID) */ -typedef struct { - uint8_t RAPID:6; - uint8_t T:1; - uint8_t E:1; -} __attribute__((__packed__))RA_HEADER_RAPID; - -/*!\brief MAC header of Random Access Response for backoff indicator (BI)*/ -typedef struct { - uint8_t BI:4; - uint8_t R:2; - uint8_t T:1; - uint8_t E:1; -} __attribute__((__packed__))RA_HEADER_BI; -/* -typedef struct { - uint64_t padding:16; - uint64_t t_crnti:16; - uint64_t hopping_flag:1; - uint64_t rb_alloc:10; - uint64_t mcs:4; - uint64_t TPC:3; - uint64_t UL_delay:1; - uint64_t cqi_req:1; - uint64_t Timing_Advance_Command:11; // first/2nd octet LSB - uint64_t R:1; // octet MSB - } __attribute__((__packed__))RAR_PDU; - -typedef struct { - uint64_t padding:16; - uint64_t R:1; // octet MSB - uint64_t Timing_Advance_Command:11; // first/2nd octet LSB - uint64_t cqi_req:1; - uint64_t UL_delay:1; - uint64_t TPC:3; - uint64_t mcs:4; - uint64_t rb_alloc:10; - uint64_t hopping_flag:1; - uint64_t t_crnti:16; - } __attribute__((__packed__))RAR_PDU; - -#define sizeof_RAR_PDU 6 -*/ -/*!\brief MAC subheader short with 7bit Length field */ -typedef struct { - uint8_t LCID:5; // octet 1 LSB - uint8_t E:1; - uint8_t R:2; // octet 1 MSB - uint8_t L:7; // octet 2 LSB - uint8_t F:1; // octet 2 MSB -} __attribute__((__packed__))SCH_SUBHEADER_SHORT; -/*!\brief MAC subheader long with 15bit Length field */ -typedef struct { - uint8_t LCID:5; // octet 1 LSB - uint8_t E:1; - uint8_t R:2; // octet 1 MSB - uint8_t L_MSB:7; - uint8_t F:1; // octet 2 MSB - uint8_t L_LSB:8; - uint8_t padding; -} __attribute__((__packed__))SCH_SUBHEADER_LONG; -/*!\brief MAC subheader short without length field */ -typedef struct { - uint8_t LCID:5; - uint8_t E:1; - uint8_t R:2; -} __attribute__((__packed__))SCH_SUBHEADER_FIXED; - -/*!\brief mac control element: short buffer status report for a specific logical channel group ID*/ -typedef struct { - uint8_t Buffer_size:6; // octet 1 LSB - uint8_t LCGID:2; // octet 1 MSB -} __attribute__((__packed__))BSR_SHORT; - -typedef BSR_SHORT BSR_TRUNCATED; -/*!\brief mac control element: long buffer status report for all logical channel group ID*/ -typedef struct { - uint8_t Buffer_size3:6; - uint8_t Buffer_size2:6; - uint8_t Buffer_size1:6; - uint8_t Buffer_size0:6; -} __attribute__((__packed__))BSR_LONG; - -#define BSR_LONG_SIZE (sizeof(BSR_LONG)) -/*!\brief mac control element: timing advance */ -typedef struct { - uint8_t TA:6; - uint8_t R:2; -} __attribute__((__packed__))TIMING_ADVANCE_CMD; -/*!\brief mac control element: power headroom report */ -typedef struct { - uint8_t PH:6; - uint8_t R:2; -} __attribute__((__packed__))POWER_HEADROOM_CMD; - -/*! \brief MIB payload */ -typedef struct { - uint8_t payload[3] ; -} __attribute__((__packed__))MIB_PDU; -/*! \brief CCCH payload */ -typedef struct { - uint8_t payload[CCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))CCCH_PDU; -/*! \brief BCCH payload */ -typedef struct { - uint8_t payload[BCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))BCCH_PDU; -/*! \brief RAR payload */ -typedef struct { - uint8_t payload[RAR_PAYLOAD_SIZE_MAX]; -} __attribute__ ((__packed__)) RAR_PDU; -/*! \brief BCCH payload */ -typedef struct { - uint8_t payload[PCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))PCCH_PDU; - -/*! \brief MCCH payload */ -typedef struct { - uint8_t payload[MCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))MCCH_PDU; -/*!< \brief MAC control element for activation and deactivation of component carriers */ -typedef struct { - uint8_t C7:1;/*!< \brief Component carrier 7 */ - uint8_t C6:1;/*!< \brief Component carrier 6 */ - uint8_t C5:1;/*!< \brief Component carrier 5 */ - uint8_t C4:1;/*!< \brief Component carrier 4 */ - uint8_t C3:1;/*!< \brief Component carrier 3 */ - uint8_t C2:1;/*!< \brief Component carrier 2 */ - uint8_t C1:1;/*!< \brief Component carrier 1 */ - uint8_t R:1;/*!< \brief Reserved */ -} __attribute__((__packed__))CC_ELEMENT; -/*! \brief MAC control element: MCH Scheduling Information */ -typedef struct { - uint8_t stop_sf_MSB:3; // octet 1 LSB - uint8_t lcid:5; // octet 2 MSB - uint8_t stop_sf_LSB:8; -} __attribute__((__packed__))MSI_ELEMENT; -/*! \brief Values of CCCH LCID for DLSCH */ -#define CCCH_LCHANID 0 -/*!\brief Values of BCCH logical channel (fake)*/ -#define BCCH 3 // SI -/*!\brief Values of PCCH logical channel (fake)*/ -#define PCCH 4 // Paging -/*!\brief Values of PCCH logical channel (fake) */ -#define MIBCH 5 // MIB -/*!\brief Values of BCCH SIB1_BR logical channel (fake) */ -#define BCCH_SIB1_BR 6 // SIB1_BR -/*!\brief Values of BCCH SIB_BR logical channel (fake) */ -#define BCCH_SI_BR 7 // SI-BR -/*!\brief Value of CCCH / SRB0 logical channel */ -#define CCCH 0 // srb0 -/*!\brief DCCH / SRB1 logical channel */ -#define DCCH 1 // srb1 -/*!\brief DCCH1 / SRB2 logical channel */ -#define DCCH1 2 // srb2 -/*!\brief DTCH DRB1 logical channel */ -#define DTCH 3 // LCID -/*!\brief MCCH logical channel */ -#define MCCH 11 -/*!\brief MTCH logical channel */ -#define MTCH 1 -// DLSCH LCHAN ID -/*!\brief LCID of UE contention resolution identity for DLSCH*/ -#define UE_CONT_RES 28 -/*!\brief LCID of timing advance for DLSCH */ -#define TIMING_ADV_CMD 29 -/*!\brief LCID of discontinous reception mode for DLSCH */ -#define DRX_CMD 30 -/*!\brief LCID of padding LCID for DLSCH */ -#define SHORT_PADDING 31 - -// MCH LCHAN IDs (table6.2.1-4 TS36.321) -/*!\brief LCID of MCCH for DL */ -#define MCCH_LCHANID 0 -/*!\brief LCID of MCH scheduling info for DL */ -#define MCH_SCHDL_INFO 3 -/*!\brief LCID of Carrier component activation/deactivation */ -#define CC_ACT_DEACT 27 - -// ULSCH LCHAN IDs -/*!\brief LCID of extended power headroom for ULSCH */ -#define EXTENDED_POWER_HEADROOM 25 -/*!\brief LCID of power headroom for ULSCH */ -#define POWER_HEADROOM 26 -/*!\brief LCID of CRNTI for ULSCH */ -#define CRNTI 27 -/*!\brief LCID of truncated BSR for ULSCH */ -#define TRUNCATED_BSR 28 -/*!\brief LCID of short BSR for ULSCH */ -#define SHORT_BSR 29 -/*!\brief LCID of long BSR for ULSCH */ -#define LONG_BSR 30 -/*!\bitmaps for BSR Triggers */ -#define BSR_TRIGGER_NONE (0) /* No BSR Trigger */ -#define BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */ -#define BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */ -#define BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */ - - -/*! \brief Downlink SCH PDU Structure */ -typedef struct { - uint8_t payload[8][SCH_PAYLOAD_SIZE_MAX]; - uint16_t Pdu_size[8]; -} __attribute__ ((__packed__)) DLSCH_PDU; - - -/*! \brief MCH PDU Structure */ -typedef struct { - int8_t payload[SCH_PAYLOAD_SIZE_MAX]; - uint16_t Pdu_size; - uint8_t mcs; - uint8_t sync_area; - uint8_t msi_active; - uint8_t mcch_active; - uint8_t mtch_active; -} __attribute__ ((__packed__)) MCH_PDU; - -/*! \brief Uplink SCH PDU Structure */ -typedef struct { - int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ - uint16_t Pdu_size; -} __attribute__ ((__packed__)) ULSCH_PDU; - -#include "PHY/impl_defs_top.h" - -/*!\brief UE ULSCH scheduling states*/ -typedef enum { - S_UL_NONE =0, - S_UL_WAITING, - S_UL_SCHEDULED, - S_UL_BUFFERED, - S_UL_NUM_STATUS -} UE_ULSCH_STATUS; - -/*!\brief UE DLSCH scheduling states*/ -typedef enum { - S_DL_NONE =0, - S_DL_WAITING, - S_DL_SCHEDULED, - S_DL_BUFFERED, - S_DL_NUM_STATUS -} UE_DLSCH_STATUS; - -/*!\brief scheduling policy for the contention-based access */ -typedef enum { - CBA_ES=0, /// equal share of RB among groups w - CBA_ES_S, /// equal share of RB among groups with small allocation - CBA_PF, /// proportional fair (kind of) - CBA_PF_S, /// proportional fair (kind of) with small RB allocation - CBA_RS /// random allocation -} CBA_POLICY; - - -/*! \brief temporary struct for ULSCH sched */ -typedef struct { - rnti_t rnti; - uint16_t subframe; - uint16_t serving_num; - UE_ULSCH_STATUS status; -} eNB_ULSCH_INFO; -/*! \brief temp struct for DLSCH sched */ -typedef struct { - rnti_t rnti; - uint16_t weight; - uint16_t subframe; - uint16_t serving_num; - UE_DLSCH_STATUS status; -} eNB_DLSCH_INFO; -/*! \brief eNB overall statistics */ -typedef struct { - /// num BCCH PDU per CC - uint32_t total_num_bcch_pdu; - /// BCCH buffer size - uint32_t bcch_buffer; - /// total BCCH buffer size - uint32_t total_bcch_buffer; - /// BCCH MCS - uint32_t bcch_mcs; - - /// num CCCH PDU per CC - uint32_t total_num_ccch_pdu; - /// BCCH buffer size - uint32_t ccch_buffer; - /// total BCCH buffer size - uint32_t total_ccch_buffer; - /// BCCH MCS - uint32_t ccch_mcs; - - /// num active users - uint16_t num_dlactive_UEs; - /// available number of PRBs for a give SF - uint16_t available_prbs; - /// total number of PRB available for the user plane - uint32_t total_available_prbs; - /// aggregation - /// total avilable nccc : num control channel element - uint16_t available_ncces; - // only for a new transmission, should be extended for retransmission - // current dlsch bit rate for all transport channels - uint32_t dlsch_bitrate; - // - uint32_t dlsch_bytes_tx; - // - uint32_t dlsch_pdus_tx; - // - uint32_t total_dlsch_bitrate; - // - uint32_t total_dlsch_bytes_tx; - // - uint32_t total_dlsch_pdus_tx; - - // here for RX - // - uint32_t ulsch_bitrate; - // - uint32_t ulsch_bytes_rx; - // - uint64_t ulsch_pdus_rx; - - uint32_t total_ulsch_bitrate; - // - uint32_t total_ulsch_bytes_rx; - // - uint32_t total_ulsch_pdus_rx; - - - /// MAC agent-related stats - /// total number of scheduling decisions - int sched_decisions; - /// missed deadlines - int missed_deadlines; - -} eNB_STATS; -/*! \brief eNB statistics for the connected UEs*/ -typedef struct { - - /// CRNTI of UE - rnti_t crnti; ///user id (rnti) of connected UEs - // rrc status - uint8_t rrc_status; - /// harq pid - uint8_t harq_pid; - /// harq rounf - uint8_t harq_round; - /// total available number of PRBs for a new transmission - uint16_t rbs_used; - /// total available number of PRBs for a retransmission - uint16_t rbs_used_retx; - /// total nccc used for a new transmission: num control channel element - uint16_t ncce_used; - /// total avilable nccc for a retransmission: num control channel element - uint16_t ncce_used_retx; - - // mcs1 before the rate adaptaion - uint8_t dlsch_mcs1; - /// Target mcs2 after rate-adaptation - uint8_t dlsch_mcs2; - // current TBS with mcs2 - uint32_t TBS; - // total TBS with mcs2 - // uint32_t total_TBS; - // total rb used for a new transmission - uint32_t total_rbs_used; - // total rb used for retransmission - uint32_t total_rbs_used_retx; - - /// TX - /// Num pkt - uint32_t num_pdu_tx[NB_RB_MAX]; - /// num bytes - uint32_t num_bytes_tx[NB_RB_MAX]; - /// num retransmission / harq - uint32_t num_retransmission; - /// instantaneous tx throughput for each TTI - // uint32_t tti_throughput[NB_RB_MAX]; - - /// overall - // - uint32_t dlsch_bitrate; - //total - uint32_t total_dlsch_bitrate; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t overhead_bytes; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t total_overhead_bytes; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t avg_overhead_bytes; - // MAC multiplexed payload - uint64_t total_sdu_bytes; - // total MAC pdu bytes - uint64_t total_pdu_bytes; - - // total num pdu - uint32_t total_num_pdus; - // - // uint32_t avg_pdu_size; - - /// RX - - /// PUCCH1a/b power (dBm) - int32_t Po_PUCCH_dBm; - /// Indicator that Po_PUCCH has been updated by PHY - int32_t Po_PUCCH_update; - /// Uplink measured RSSI - int32_t UL_rssi; - /// preassigned mcs after rate adaptation - uint8_t ulsch_mcs1; - /// adjusted mcs - uint8_t ulsch_mcs2; - - /// estimated average pdu inter-departure time - uint32_t avg_pdu_idt; - /// estimated average pdu size - uint32_t avg_pdu_ps; - /// - uint32_t aggregated_pdu_size; - uint32_t aggregated_pdu_arrival; - - /// uplink transport block size - uint32_t ulsch_TBS; - - /// total rb used for a new uplink transmission - uint32_t num_retransmission_rx; - /// total rb used for a new uplink transmission - uint32_t rbs_used_rx; - /// total rb used for a new uplink retransmission - uint32_t rbs_used_retx_rx; - /// total rb used for a new uplink transmission - uint32_t total_rbs_used_rx; - /// snr - int32_t snr; - /// target snr - int32_t target_snr; - - /// num rx pdu - uint32_t num_pdu_rx[NB_RB_MAX]; - /// num bytes rx - uint32_t num_bytes_rx[NB_RB_MAX]; - /// instantaneous rx throughput for each TTI - // uint32_t tti_goodput[NB_RB_MAX]; - /// errors - uint32_t num_errors_rx; - - uint64_t overhead_bytes_rx; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t total_overhead_bytes_rx; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t avg_overhead_bytes_rx; - // - uint32_t ulsch_bitrate; - //total - uint32_t total_ulsch_bitrate; - /// overall - /// MAC pdu bytes - uint64_t pdu_bytes_rx; - /// total MAC pdu bytes - uint64_t total_pdu_bytes_rx; - /// total num pdu - uint32_t total_num_pdus_rx; - /// num of error pdus - uint32_t total_num_errors_rx; - -} eNB_UE_STATS; -/*! \brief eNB template for UE context information */ -typedef struct { - /// C-RNTI of UE - rnti_t rnti; - /// NDI from last scheduling - uint8_t oldNDI[8]; - /// mcs1 from last scheduling - uint8_t oldmcs1[8]; - /// mcs2 from last scheduling - uint8_t oldmcs2[8]; - /// NDI from last UL scheduling - uint8_t oldNDI_UL[8]; - /// mcs from last UL scheduling - uint8_t mcs_UL[8]; - /// TBS from last UL scheduling - uint8_t TBS_UL[8]; - /// CQI_req from last scheduling - uint8_t oldCQI_UL[8]; - /// TPC from last scheduling - uint8_t oldTPC_UL[8]; - /// Flag to indicate UL has been scheduled at least once - boolean_t ul_active; - /// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received) - boolean_t configured; - - /// MCS from last scheduling - uint8_t mcs[8]; - - /// TPC from last scheduling - uint8_t oldTPC[8]; - - // PHY interface info - - /// Number of Allocated RBs for DL after scheduling (prior to frequency allocation) - uint16_t nb_rb[8]; // num_max_harq - - /// Number of Allocated RBs for UL after scheduling - uint16_t nb_rb_ul[8]; // num_max_harq - - /// Number of Allocated RBs for UL after scheduling - uint16_t first_rb_ul[8]; // num_max_harq - - /// Is CQI requested for UL after scheduling 1st transmission - uint8_t cqi_req[8]; // num_max_harq - - /// Cyclic shift for DMRS after scheduling - uint16_t cshift[8]; // num_max_harq - - /// Number of Allocated RBs by the ulsch preprocessor - uint8_t pre_allocated_nb_rb_ul; - - /// index of Allocated RBs by the ulsch preprocessor - int8_t pre_allocated_rb_table_index_ul; - - /// total allocated RBs - int8_t total_allocated_rbs; - - /// pre-assigned MCS by the ulsch preprocessor - uint8_t pre_assigned_mcs_ul; - - /// assigned MCS by the ulsch scheduler - uint8_t assigned_mcs_ul; - - /// DL DAI - uint8_t DAI; - - /// UL DAI - uint8_t DAI_ul[10]; - - /// UL Scheduling Request Received - uint8_t ul_SR; - - ///Resource Block indication for each sub-band in MU-MIMO - uint8_t rballoc_subband[8][50]; - - // Logical channel info for link with RLC - - /// Last received UE BSR info for each logical channel group id - uint8_t bsr_info[MAX_NUM_LCGID]; - - /// LCGID mapping - long lcgidmap[11]; - - /// phr information - int8_t phr_info; - - /// phr information - int8_t phr_info_configured; - - ///dl buffer info - uint32_t dl_buffer_info[MAX_NUM_LCID]; - /// total downlink buffer info - uint32_t dl_buffer_total; - /// total downlink pdus - uint32_t dl_pdus_total; - /// downlink pdus for each LCID - uint32_t dl_pdus_in_buffer[MAX_NUM_LCID]; - /// creation time of the downlink buffer head for each LCID - uint32_t dl_buffer_head_sdu_creation_time[MAX_NUM_LCID]; - /// maximum creation time of the downlink buffer head across all LCID - uint32_t dl_buffer_head_sdu_creation_time_max; - /// a flag indicating that the downlink head SDU is segmented - uint8_t dl_buffer_head_sdu_is_segmented[MAX_NUM_LCID]; - /// size of remaining size to send for the downlink head SDU - uint32_t dl_buffer_head_sdu_remaining_size_to_send[MAX_NUM_LCID]; - - /// total uplink buffer size - uint32_t ul_total_buffer; - /// uplink buffer creation time for each LCID - uint32_t ul_buffer_creation_time[MAX_NUM_LCGID]; - /// maximum uplink buffer creation time across all the LCIDs - uint32_t ul_buffer_creation_time_max; - /// uplink buffer size per LCID - uint32_t ul_buffer_info[MAX_NUM_LCGID]; - - /// UE tx power - int32_t ue_tx_power; - - /// stores the frame where the last TPC was transmitted - uint32_t pusch_tpc_tx_frame; - uint32_t pusch_tpc_tx_subframe; - uint32_t pucch_tpc_tx_frame; - uint32_t pucch_tpc_tx_subframe; - -#ifdef LOCALIZATION - eNB_UE_estimated_distances distance; -#endif - - - uint8_t rach_resource_type; - - uint16_t mpdcch_repetition_cnt; - struct PhysicalConfigDedicated *physicalConfigDedicated; - frame_t Msg2_frame; - sub_frame_t Msg2_subframe; - -} UE_TEMPLATE; - -/*! \brief scheduling control information set through an API (not used)*/ -typedef struct { - ///UL transmission bandwidth in RBs - uint8_t ul_bandwidth[MAX_NUM_LCID]; - ///DL transmission bandwidth in RBs - uint8_t dl_bandwidth[MAX_NUM_LCID]; - - //To do GBR bearer - uint8_t min_ul_bandwidth[MAX_NUM_LCID]; - - uint8_t min_dl_bandwidth[MAX_NUM_LCID]; - - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateDL; - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateUL; - ///CQI scheduling interval in subframes. - uint16_t cqiSchedInterval; - ///Contention resolution timer used during random access - uint8_t mac_ContentionResolutionTimer; - - uint16_t max_allowed_rbs[MAX_NUM_LCID]; - - uint8_t max_mcs[MAX_NUM_LCID]; - - uint16_t priority[MAX_NUM_LCID]; - - // resource scheduling information - - /// Current DL harq round per harq_pid on each CC - uint8_t round[MAX_NUM_CCs][10]; - /// Current Active TBs per harq_pid on each CC - uint8_t tbcnt[MAX_NUM_CCs][10]; - /// Current UL harq round per harq_pid on each CC - uint8_t round_UL[MAX_NUM_CCs][8]; - uint8_t dl_pow_off[MAX_NUM_CCs]; - uint16_t pre_nb_available_rbs[MAX_NUM_CCs]; - unsigned char rballoc_sub_UE[MAX_NUM_CCs][N_RBG_MAX]; - uint16_t ta_timer; - int16_t ta_update; - uint16_t ul_consecutive_errors; - int32_t context_active_timer; - int32_t cqi_req_timer; - int32_t ul_inactivity_timer; - int32_t ul_failure_timer; - int32_t ul_scheduled; - int32_t ra_pdcch_order_sent; - int32_t ul_out_of_sync; - int32_t phr_received; - uint8_t periodic_ri_received[NFAPI_CC_MAX]; - uint8_t aperiodic_ri_received[NFAPI_CC_MAX]; - uint32_t pucch_tpc_accumulated[NFAPI_CC_MAX]; - uint8_t pucch1_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch1_snr[NFAPI_CC_MAX]; - uint8_t pucch2_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch2_snr[NFAPI_CC_MAX]; - uint8_t pucch3_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch3_snr[NFAPI_CC_MAX]; - uint8_t pusch_snr[NFAPI_CC_MAX]; - uint16_t feedback_cnt[NFAPI_CC_MAX]; - uint16_t timing_advance; - uint16_t timing_advance_r9; - uint8_t periodic_wideband_cqi[NFAPI_CC_MAX]; - uint8_t periodic_wideband_spatial_diffcqi[NFAPI_CC_MAX]; - uint8_t periodic_wideband_pmi[NFAPI_CC_MAX]; - uint8_t periodic_subband_cqi[NFAPI_CC_MAX][16]; - uint8_t periodic_subband_spatial_diffcqi[NFAPI_CC_MAX][16]; - uint8_t aperiodic_subband_cqi0[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_pmi[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_diffcqi0[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_cqi1[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_diffcqi1[NFAPI_CC_MAX][25]; - uint8_t aperiodic_wideband_cqi0[NFAPI_CC_MAX]; - uint8_t aperiodic_wideband_pmi[NFAPI_CC_MAX]; - uint8_t aperiodic_wideband_cqi1[NFAPI_CC_MAX]; - uint8_t aperiodic_wideband_pmi1[NFAPI_CC_MAX]; - uint8_t dl_cqi[NFAPI_CC_MAX]; -} UE_sched_ctrl; -/*! \brief eNB template for the Random access information */ -typedef struct { - /// Flag to indicate this process is active - boolean_t RA_active; - /// Size of DCI for RA-Response (bytes) - uint8_t RA_dci_size_bytes1; - /// Size of DCI for RA-Response (bits) - uint8_t RA_dci_size_bits1; - /// Actual DCI to transmit for RA-Response - uint8_t RA_alloc_pdu1[(MAX_DCI_SIZE_BITS>>3)+1]; - /// DCI format for RA-Response (should be 1A) - uint8_t RA_dci_fmt1; - /// Size of DCI for Msg4/ContRes (bytes) - uint8_t RA_dci_size_bytes2; - /// Size of DCI for Msg4/ContRes (bits) - uint8_t RA_dci_size_bits2; - /// Actual DCI to transmit for Msg4/ContRes - uint8_t RA_alloc_pdu2[(MAX_DCI_SIZE_BITS>>3)+1]; - /// DCI format for Msg4/ContRes (should be 1A) - uint8_t RA_dci_fmt2; - /// Flag to indicate the eNB should generate RAR. This is triggered by detection of PRACH - uint8_t generate_rar; - /// Subframe where preamble was received - uint8_t preamble_subframe; - /// Subframe where Msg2 is to be sent - uint8_t Msg2_subframe; - /// Frame where Msg2 is to be sent - frame_t Msg2_frame; - /// Subframe where Msg3 is to be sent - sub_frame_t Msg3_subframe; - /// Frame where Msg3 is to be sent - frame_t Msg3_frame; - /// Subframe where Msg4 is to be sent - sub_frame_t Msg4_subframe; - /// Frame where Msg4 is to be sent - frame_t Msg4_frame; - /// Flag to indicate the eNB should generate Msg4 upon reception of SDU from RRC. This is triggered by first ULSCH reception at eNB for new user. - uint8_t generate_Msg4; - /// Flag to indicate that eNB is waiting for ACK that UE has received Msg3. - uint8_t wait_ack_Msg4; - /// harq_pid used for Msg4 transmission - uint8_t harq_pid; - /// UE RNTI allocated during RAR - rnti_t rnti; - /// RA RNTI allocated from received PRACH - uint16_t RA_rnti; - /// Received preamble_index - uint8_t preamble_index; - /// Received UE Contention Resolution Identifier - uint8_t cont_res_id[6]; - /// Timing offset indicated by PHY - int16_t timing_offset; - /// Timeout for RRC connection - int16_t RRC_timer; - /// Msg3 first RB - uint8_t msg3_first_rb; - /// Msg3 number of RB - uint8_t msg3_nb_rb; - /// Msg3 MCS - uint8_t msg3_mcs; - /// Msg3 TPC command - uint8_t msg3_TPC; - /// Msg3 ULdelay command - uint8_t msg3_ULdelay; - /// Msg3 cqireq command - uint8_t msg3_cqireq; - /// Round of Msg3 HARQ - uint8_t msg3_round; - /// TBS used for Msg4 - int msg4_TBsize; - /// MCS used for Msg4 - int msg4_mcs; - /// size off piggybacked RRC SDU - uint8_t msg4_rrc_sdu_length; - uint32_t msg4_delay; - uint8_t rach_resource_type; - uint8_t msg2_mpdcch_repetition_cnt; - uint8_t msg2_mpdcch_done; - uint8_t msg4_mpdcch_repetition_cnt; - uint8_t msg4_mpdcch_done; - uint8_t msg2_narrowband; - uint32_t msg34_narrowband; -} RA_TEMPLATE; - - -/*! \brief subband bitmap confguration (for ALU icic algo purpose), in test phase */ -typedef struct { - uint8_t sbmap[NUMBER_OF_SUBBANDS_MAX]; //13 = number of SB MAX for 100 PRB - uint8_t periodicity; - uint8_t first_subframe; - uint8_t sb_size; - uint8_t nb_active_sb; -} SBMAP_CONF; -/*! \brief UE list used by eNB to order UEs/CC for scheduling*/ -typedef struct { - /// Dedicated information for UEs - struct PhysicalConfigDedicated *physicalConfigDedicated[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// DLSCH pdu - DLSCH_PDU DLSCH_pdu[MAX_NUM_CCs][2][NUMBER_OF_UE_MAX]; - /// DCI template and MAC connection parameters for UEs - UE_TEMPLATE UE_template[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// DCI template and MAC connection for RA processes - int pCC_id[NUMBER_OF_UE_MAX]; - /// sorted downlink component carrier for the scheduler - int ordered_CCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// number of downlink active component carrier - int numactiveCCs[NUMBER_OF_UE_MAX]; - /// sorted uplink component carrier for the scheduler - int ordered_ULCCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// number of uplink active component carrier - int numactiveULCCs[NUMBER_OF_UE_MAX]; - /// number of downlink active component carrier - uint8_t dl_CC_bitmap[NUMBER_OF_UE_MAX]; - /// eNB to UE statistics - eNB_UE_STATS eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// scheduling control info - UE_sched_ctrl UE_sched_ctrl[NUMBER_OF_UE_MAX]; - int next[NUMBER_OF_UE_MAX]; - int head; - int next_ul[NUMBER_OF_UE_MAX]; - int head_ul; - int avail; - int num_UEs; - boolean_t active[NUMBER_OF_UE_MAX]; -} UE_list_t; - -/*! \brief eNB common channels */ -typedef struct { - int physCellId; - int p_eNB; - int Ncp; - int eutra_band; - uint32_t dl_CarrierFreq; - BCCH_BCH_Message_t *mib; - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon; - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon_BR; - TDD_Config_t *tdd_Config; - SchedulingInfoList_t *schedulingInfoList; - ARFCN_ValueEUTRA_t ul_CarrierFreq; - long ul_Bandwidth; - /// Outgoing MIB PDU for PHY - MIB_PDU MIB_pdu; - /// Outgoing BCCH pdu for PHY - BCCH_PDU BCCH_pdu; - /// Outgoing BCCH DCI allocation - uint32_t BCCH_alloc_pdu; - /// Outgoing CCCH pdu for PHY - CCCH_PDU CCCH_pdu; - /// Outgoing RAR pdu for PHY - RAR_PDU RAR_pdu; - /// Template for RA computations - RA_TEMPLATE RA_template[NB_RA_PROC_MAX]; - /// VRB map for common channels - uint8_t vrb_map[100]; - /// VRB map for common channels and retransmissions by PHICH - uint8_t vrb_map_UL[100]; - /// MBSFN SubframeConfig - struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; - /// number of subframe allocation pattern available for MBSFN sync area - uint8_t num_sf_allocation_pattern; - /// MBMS Flag - uint8_t MBMS_flag; - /// Outgoing MCCH pdu for PHY - MCCH_PDU MCCH_pdu; - /// MCCH active flag - uint8_t msi_active; - /// MCCH active flag - uint8_t mcch_active; - /// MTCH active flag - uint8_t mtch_active; - /// number of active MBSFN area - uint8_t num_active_mbsfn_area; - /// MBSFN Area Info - struct MBSFN_AreaInfo_r9 *mbsfn_AreaInfo[MAX_MBSFN_AREA]; - /// PMCH Config - struct PMCH_Config_r9 *pmch_Config[MAX_PMCH_perMBSFN]; - /// MBMS session info list - struct MBMS_SessionInfoList_r9 *mbms_SessionList[MAX_PMCH_perMBSFN]; - /// Outgoing MCH pdu for PHY - MCH_PDU MCH_pdu; - /// Rel13 parameters from SIB1 - SystemInformationBlockType1_v1310_IEs_t *sib1_v13ext; - /// Counter for SIB1-BR scheduling - int SIB1_BR_cnt; - /// Outgoing BCCH-BR pdu for PHY - BCCH_PDU BCCH_BR_pdu[20]; -} COMMON_channels_t; -/*! \brief top level eNB MAC structure */ -typedef struct eNB_MAC_INST_s { - /// Ethernet parameters for northbound midhaul interface - eth_params_t eth_params_n; - /// Ethernet parameters for fronthaul interface - eth_params_t eth_params_s; - /// - module_id_t Mod_id; - /// frame counter - frame_t frame; - /// subframe counter - sub_frame_t subframe; - /// Pointer to IF module instance for PHY - IF_Module_t *if_inst; - /// Common cell resources - COMMON_channels_t common_channels[MAX_NUM_CCs]; - /// current PDU index (BCH,MCH,DLSCH) - uint16_t pdu_index[MAX_NUM_CCs]; - - /// NFAPI Config Request Structure - nfapi_config_request_t config[MAX_NUM_CCs]; - /// Preallocated DL pdu list - nfapi_dl_config_request_pdu_t dl_config_pdu_list[MAX_NUM_CCs][MAX_NUM_DL_PDU]; - /// NFAPI DL Config Request Structure - nfapi_dl_config_request_t DL_req[MAX_NUM_CCs]; - /// Preallocated UL pdu list - nfapi_ul_config_request_pdu_t ul_config_pdu_list[MAX_NUM_CCs][MAX_NUM_UL_PDU]; - /// Preallocated UL pdu list for ULSCH (n+k delay) - nfapi_ul_config_request_pdu_t ul_config_pdu_list_tmp[MAX_NUM_CCs][10][MAX_NUM_UL_PDU]; - /// NFAPI UL Config Request Structure, send to L1 4 subframes before processing takes place - nfapi_ul_config_request_t UL_req[MAX_NUM_CCs]; - /// NFAPI "Temporary" UL Config Request Structure, holds future UL_config requests - nfapi_ul_config_request_t UL_req_tmp[MAX_NUM_CCs][10]; - /// Preallocated HI_DCI0 pdu list - nfapi_hi_dci0_request_pdu_t hi_dci0_pdu_list[MAX_NUM_CCs][MAX_NUM_HI_DCI0_PDU]; - /// NFAPI HI/DCI0 Config Request Structure - nfapi_hi_dci0_request_t HI_DCI0_req[MAX_NUM_CCs]; - /// Prealocated TX pdu list - nfapi_tx_request_pdu_t tx_request_pdu[MAX_NUM_CCs][MAX_NUM_TX_REQUEST_PDU]; - /// NFAPI DL PDU structure - nfapi_tx_request_t TX_req[MAX_NUM_CCs]; - /// UL handle - uint32_t ul_handle; - UE_list_t UE_list; - - ///subband bitmap configuration - SBMAP_CONF sbmap_conf; - /// CCE table used to build DCI scheduling information - int CCE_table[MAX_NUM_CCs][800]; - /// active flag for Other lcid - uint8_t lcid_active[NB_RB_MAX]; - /// eNB stats - eNB_STATS eNB_stats[MAX_NUM_CCs]; - // MAC function execution peformance profiler - /// processing time of eNB scheduler - time_stats_t eNB_scheduler; - /// processing time of eNB scheduler for SI - time_stats_t schedule_si; - /// processing time of eNB scheduler for Random access - time_stats_t schedule_ra; - /// processing time of eNB ULSCH scheduler - time_stats_t schedule_ulsch; - /// processing time of eNB DCI generation - time_stats_t fill_DLSCH_dci; - /// processing time of eNB MAC preprocessor - time_stats_t schedule_dlsch_preprocessor; - /// processing time of eNB DLSCH scheduler - time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor - /// processing time of eNB MCH scheduler - time_stats_t schedule_mch; - /// processing time of eNB ULSCH reception - time_stats_t rx_ulsch_sdu; // include rlc_data_ind -} eNB_MAC_INST; - -/* - * UE part - */ - -typedef enum { - TYPE0, - TYPE1, - TYPE1A, - TYPE2, - TYPE2A, - TYPEUESPEC -} MPDCCH_TYPES_t; - -/*!\brief UE layer 2 status */ -typedef enum { - CONNECTION_OK=0, - CONNECTION_LOST, - PHY_RESYNCH, - PHY_HO_PRACH -} UE_L2_STATE_t; - -/*!\brief UE scheduling info */ -typedef struct { - /// buffer status for each lcgid - uint8_t BSR[MAX_NUM_LCGID]; // should be more for mesh topology - /// keep the number of bytes in rlc buffer for each lcgid - int32_t BSR_bytes[MAX_NUM_LCGID]; - /// after multiplexing buffer remain for each lcid - int32_t LCID_buffer_remain[MAX_NUM_LCID]; - /// sum of all lcid buffer size - uint16_t All_lcid_buffer_size_lastTTI; - /// buffer status for each lcid - uint8_t LCID_status[MAX_NUM_LCID]; - /// SR pending as defined in 36.321 - uint8_t SR_pending; - /// SR_COUNTER as defined in 36.321 - uint16_t SR_COUNTER; - /// logical channel group ide for each LCID - uint8_t LCGID[MAX_NUM_LCID]; - /// retxBSR-Timer, default value is sf2560 - uint16_t retxBSR_Timer; - /// retxBSR_SF, number of subframe before triggering a regular BSR - uint16_t retxBSR_SF; - /// periodicBSR-Timer, default to infinity - uint16_t periodicBSR_Timer; - /// periodicBSR_SF, number of subframe before triggering a periodic BSR - uint16_t periodicBSR_SF; - /// default value is 0: not configured - uint16_t sr_ProhibitTimer; - /// sr ProhibitTime running - uint8_t sr_ProhibitTimer_Running; - /// default value to n5 - uint16_t maxHARQ_Tx; - /// default value is false - uint16_t ttiBundling; - /// default value is release - struct DRX_Config *drx_config; - /// default value is release - struct MAC_MainConfig__phr_Config *phr_config; - ///timer before triggering a periodic PHR - uint16_t periodicPHR_Timer; - ///timer before triggering a prohibit PHR - uint16_t prohibitPHR_Timer; - ///DL Pathloss change value - uint16_t PathlossChange; - ///number of subframe before triggering a periodic PHR - int16_t periodicPHR_SF; - ///number of subframe before triggering a prohibit PHR - int16_t prohibitPHR_SF; - ///DL Pathloss Change in db - uint16_t PathlossChange_db; - - /// default value is false - uint16_t extendedBSR_Sizes_r10; - /// default value is false - uint16_t extendedPHR_r10; - - //Bj bucket usage per lcid - int16_t Bj[MAX_NUM_LCID]; - // Bucket size per lcid - int16_t bucket_size[MAX_NUM_LCID]; -} UE_SCHEDULING_INFO; -/*!\brief Top level UE MAC structure */ -typedef struct { - uint16_t Node_id; - /// RX frame counter - frame_t rxFrame; - /// RX subframe counter - sub_frame_t rxSubframe; - /// TX frame counter - frame_t txFrame; - /// TX subframe counter - sub_frame_t txSubframe; - /// C-RNTI of UE - uint16_t crnti; - /// C-RNTI of UE before HO - rnti_t crnti_before_ho; ///user id (rnti) of connected UEs - /// uplink active flag - uint8_t ul_active; - /// pointer to RRC PHY configuration - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon; - /// pointer to RACH_ConfigDedicated (NULL when not active, i.e. upon HO completion or T304 expiry) - struct RACH_ConfigDedicated *rach_ConfigDedicated; - /// pointer to RRC PHY configuration - struct PhysicalConfigDedicated *physicalConfigDedicated; - /// pointer to RRC PHY configuration SCEll - struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10; - /// pointer to TDD Configuration (NULL for FDD) - TDD_Config_t *tdd_Config; - /// Number of adjacent cells to measure - uint8_t n_adj_cells; - /// Array of adjacent physical cell ids - uint32_t adj_cell_id[6]; - /// Pointer to RRC MAC configuration - MAC_MainConfig_t *macConfig; - /// Pointer to RRC Measurement gap configuration - MeasGapConfig_t *measGapConfig; - /// Pointers to LogicalChannelConfig indexed by LogicalChannelIdentity. Note NULL means LCHAN is inactive. - LogicalChannelConfig_t *logicalChannelConfig[MAX_NUM_LCID]; - /// Scheduling Information - UE_SCHEDULING_INFO scheduling_info; - /// Outgoing CCCH pdu for PHY - CCCH_PDU CCCH_pdu; - /// Outgoing RAR pdu for PHY - RAR_PDU RAR_pdu; - /// Incoming DLSCH pdu for PHY - DLSCH_PDU DLSCH_pdu[NUMBER_OF_UE_MAX][2]; - /// number of attempt for rach - uint8_t RA_attempt_number; - /// Random-access procedure flag - uint8_t RA_active; - /// Random-access window counter - int8_t RA_window_cnt; - /// Random-access Msg3 size in bytes - uint8_t RA_Msg3_size; - /// Random-access prachMaskIndex - uint8_t RA_prachMaskIndex; - /// Flag indicating Preamble set (A,B) used for first Msg3 transmission - uint8_t RA_usedGroupA; - /// Random-access Resources - PRACH_RESOURCES_t RA_prach_resources; - /// Random-access PREAMBLE_TRANSMISSION_COUNTER - uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; - /// Random-access backoff counter - int16_t RA_backoff_cnt; - /// Random-access variable for window calculation (frame of last change in window counter) - uint32_t RA_tx_frame; - /// Random-access variable for window calculation (subframe of last change in window counter) - uint8_t RA_tx_subframe; - /// Random-access Group B maximum path-loss - /// Random-access variable for backoff (frame of last change in backoff counter) - uint32_t RA_backoff_frame; - /// Random-access variable for backoff (subframe of last change in backoff counter) - uint8_t RA_backoff_subframe; - /// Random-access Group B maximum path-loss - uint16_t RA_maxPL; - /// Random-access Contention Resolution Timer active flag - uint8_t RA_contention_resolution_timer_active; - /// Random-access Contention Resolution Timer count value - uint8_t RA_contention_resolution_cnt; - /// power headroom reporitng reconfigured - uint8_t PHR_reconfigured; - /// power headroom state as configured by the higher layers - uint8_t PHR_state; - /// power backoff due to power management (as allowed by P-MPRc) for this cell - uint8_t PHR_reporting_active; - /// power backoff due to power management (as allowed by P-MPRc) for this cell - uint8_t power_backoff_db[NUMBER_OF_eNB_MAX]; - /// BSR report falg management - uint8_t BSR_reporting_active; - /// retxBSR-Timer expires flag - uint8_t retxBSRTimer_expires_flag; - /// periodBSR-Timer expires flag - uint8_t periodBSRTimer_expires_flag; - - /// MBSFN_Subframe Configuration - struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA? - /// number of subframe allocation pattern available for MBSFN sync area - uint8_t num_sf_allocation_pattern; - /// number of active MBSFN area - uint8_t num_active_mbsfn_area; - /// MBSFN Area Info - struct MBSFN_AreaInfo_r9 *mbsfn_AreaInfo[MAX_MBSFN_AREA]; - /// PMCH Config - struct PMCH_Config_r9 *pmch_Config[MAX_PMCH_perMBSFN]; - /// MCCH status - uint8_t mcch_status; - /// MSI status - uint8_t msi_status;// could be an array if there are >1 MCH in one MBSFN area - /// CBA RNTI for each group - uint16_t cba_rnti[NUM_MAX_CBA_GROUP]; - /// last SFN for CBA channel access - uint8_t cba_last_access[NUM_MAX_CBA_GROUP]; - /// total UE scheduler processing time - time_stats_t ue_scheduler; // total - /// UE ULSCH tx processing time inlcuding RLC interface (rlc_data_req) and mac header generation - time_stats_t tx_ulsch_sdu; - /// UE DLSCH rx processing time inlcuding RLC interface (mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind) and mac header parser - time_stats_t rx_dlsch_sdu ; - /// UE query for MCH subframe processing time - time_stats_t ue_query_mch; - /// UE MCH rx processing time - time_stats_t rx_mch_sdu; - /// UE BCCH rx processing time including RLC interface (mac_rrc_data_ind) - time_stats_t rx_si; - /// UE PCCH rx processing time including RLC interface (mac_rrc_data_ind) - time_stats_t rx_p; -} UE_MAC_INST; -/*! \brief ID of the neighboring cells used for HO*/ -typedef struct { - uint16_t cell_ids[6]; - uint8_t n_adj_cells; -} neigh_cell_id_t; - -#include "proto.h" -/*@}*/ -#endif /*__LAYER2_MAC_DEFS_H__ */ diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 0d0d0e7123..b900bef5bf 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -35,7 +35,7 @@ #include "LAYER2/MAC/mac_extern.h" #include "LAYER2/MAC/mac_proto.h" -#include "NR_MAC_gNB/mac_proto.h" + #include "common/utils/LOG/log.h" #include "nfapi/oai_integration/vendor_ext.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -89,7 +89,7 @@ void schedule_SRS(module_id_t module_idP, const uint16_t deltaTSFCTabType1[15][2] = { {1, 1}, {1, 2}, {2, 2}, {1, 5}, {2, 5}, {4, 5}, {8, 5}, {3, 5}, {12, 5}, {1, 10}, {2, 10}, {4, 10}, {8, 10}, {351, 10}, {383, 10} }; // Table 5.5.3.3-2 3GPP 36.211 FDD const uint16_t deltaTSFCTabType2[14][2] = { {2, 5}, {6, 5}, {10, 5}, {18, 5}, {14, 5}, {22, 5}, {26, 5}, {30, 5}, {70, 10}, {74, 10}, {194, 10}, {326, 10}, {586, 10}, {210, 10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &(eNB->UE_list); + UE_info_t *UE_info = &eNB->UE_info; nfapi_ul_config_request_body_t *ul_req = NULL; UE_sched_ctrl_t *UE_scheduling_control = NULL; COMMON_channels_t *cc = eNB->common_channels; @@ -117,7 +117,7 @@ void schedule_SRS(module_id_t module_idP, if ((1 << tmp) & deltaTSFC) { /* This is an SRS subframe, loop over UEs */ for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (!UE_list->active[UE_id]) { + if (!UE_info->active[UE_id]) { continue; } @@ -126,14 +126,14 @@ void schedule_SRS(module_id_t module_idP, continue; } - if(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) { + if(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) { LOG_E(MAC,"physicalConfigDedicated is null for UE %d\n",UE_id); printf("physicalConfigDedicated is null for UE %d\n",UE_id); return; } /* CDRX condition on Active Time and SRS type-0 report (36.321 5.7) */ - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); + UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); /* Test if Active Time not running since 6+ subframes */ if (UE_scheduling_control->cdrx_configured == TRUE && UE_scheduling_control->in_active_time == FALSE) { @@ -145,7 +145,7 @@ void schedule_SRS(module_id_t module_idP, ul_req = &(eNB->UL_req[CC_id].ul_config_request_body); - if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) { + if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) { if (soundingRS_UL_ConfigDedicated->present == LTE_SoundingRS_UL_ConfigDedicated_PR_setup) { get_srs_pos(&cc[CC_id], soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex, @@ -161,7 +161,7 @@ void schedule_SRS(module_id_t module_idP, ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_srs_pdu)); ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG; ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t)sizeof(nfapi_ul_config_srs_pdu); - ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; + ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti; ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth; ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition; ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;; @@ -173,7 +173,7 @@ void schedule_SRS(module_id_t module_idP, ul_req->number_of_pdus++; } // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset) } // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) - } // if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) + } // if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) } // end for loop on UE_id } // if((1<UE_list; + UE_info_t *UE_info = &eNB->UE_info; COMMON_channels_t *cc = NULL; nfapi_ul_config_request_body_t *ul_req = NULL; UE_sched_ctrl_t *UE_scheduling_control = NULL; @@ -205,7 +205,7 @@ void schedule_CSI(module_id_t module_idP, cc = &eNB->common_channels[CC_id]; for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == FALSE) { continue; } @@ -214,7 +214,7 @@ void schedule_CSI(module_id_t module_idP, continue; } - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", UE_id); /* @@ -222,7 +222,7 @@ void schedule_CSI(module_id_t module_idP, * Here we consider classic periodic reports on PUCCH without PUSCH simultaneous transmission condition. * TODO: add the handling or test on simultaneous PUCCH/PUSCH transmission */ - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); + UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); if (UE_scheduling_control->cdrx_configured == TRUE) { /* Test if CQI masking activated */ @@ -246,8 +246,8 @@ void schedule_CSI(module_id_t module_idP, ul_req = &(eNB->UL_req[CC_id].ul_config_request_body); - if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL) { - cqi_ReportPeriodic = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic; + if (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL) { + cqi_ReportPeriodic = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic; if (cqi_ReportPeriodic != NULL) { /* Rel8 Periodic CSI (CQI/PMI/RI) reporting */ @@ -262,10 +262,10 @@ void schedule_CSI(module_id_t module_idP, ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE; ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu)); ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG; - ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; + ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex; - ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = get_rel8_dl_cqi_pmi_size(&UE_list->UE_sched_ctrl[UE_id], CC_id, cc, get_tmode(module_idP, CC_id, UE_id), + ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = get_rel8_dl_cqi_pmi_size(&UE_info->UE_sched_ctrl[UE_id], CC_id, cc, get_tmode(module_idP, CC_id, UE_id), cqi_ReportPeriodic); ul_req->number_of_pdus++; ul_req->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; @@ -279,7 +279,7 @@ void schedule_CSI(module_id_t module_idP, ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE; ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu)); ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG; - ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; + ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = (cc->p_eNB == 2) ? 1 : 2; @@ -291,7 +291,7 @@ void schedule_CSI(module_id_t module_idP, } // if CSI Periodic is not release state } // if (cqi_ReportPeriodic != NULL) } // if cqi_ReportConfig != NULL - } // for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { + } // for (UE_id=UE_info->head; UE_id>=0; UE_id=UE_info->next[UE_id]) { } // for (CC_id=0; CC_idUE_list; + UE_info_t *UE_info = &eNB->UE_info; nfapi_ul_config_request_t *ul_req = NULL; nfapi_ul_config_request_body_t *ul_req_body = NULL; LTE_SchedulingRequestConfig_t *SRconfig = NULL; @@ -319,13 +319,13 @@ schedule_SR (module_id_t module_idP, eNB->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP; for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (!UE_list->active[UE_id]) { + if (!UE_info->active[UE_id]) { continue; } - if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) continue; + if (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) continue; - if ((SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig) != NULL) { + if ((SRconfig = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig) != NULL) { if (SRconfig->present == LTE_SchedulingRequestConfig_PR_setup) { if (SRconfig->choice.setup.sr_ConfigIndex <= 4) { // 5 ms SR period if ((subframeP % 5) != SRconfig->choice.setup.sr_ConfigIndex) continue; @@ -337,9 +337,11 @@ schedule_SR (module_id_t module_idP, if ((10 * (frameP & 3) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 35)) continue; } else if (SRconfig->choice.setup.sr_ConfigIndex <= 154) { // 80 ms SR period if ((10 * (frameP & 7) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 75)) continue; + } else if (SRconfig->choice.setup.sr_ConfigIndex <= 156) { // 2ms SR period + if ((subframeP % 2) != (SRconfig->choice.setup.sr_ConfigIndex - 155)) continue; } } // SRconfig->present == SchedulingRequestConfig_PR_setup) - } // SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) + } // SRconfig = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) /* If we get here there is some PUCCH1 reception to schedule for SR */ ul_req = &(eNB->UL_req[CC_id]); @@ -354,14 +356,14 @@ schedule_SR (module_id_t module_idP, (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE) || (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) || (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE)) && - (ul_req_body->ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) { + (ul_req_body->ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_info->UE_template[CC_id][UE_id].rnti)) { skip_ue = 1; pdu_list_index = i; break; } /* If there is already an HARQ pdu, convert to SR_HARQ */ else if ((ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) && - (ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) { + (ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == UE_info->UE_template[CC_id][UE_id].rnti)) { is_harq = 1; pdu_list_index = i; break; @@ -375,20 +377,20 @@ schedule_SR (module_id_t module_idP, frameP, subframeP, UE_id, - UE_list->UE_template[CC_id][UE_id].rnti, + UE_info->UE_template[CC_id][UE_id].rnti, is_harq); /* Check Rel10 or Rel8 SR */ - if ((UE_list-> UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) && - (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020) && - (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) { + if ((UE_info-> UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) && + (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020) && + (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) { sr.sr_information_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG; sr.sr_information_rel10.number_of_pucch_resources = 1; - sr.sr_information_rel10.pucch_index_p1 = *UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10; + sr.sr_information_rel10.pucch_index_p1 = *UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10; LOG_D(MAC, "REL10 PUCCH INDEX P1:%d \n", sr.sr_information_rel10.pucch_index_p1); } else { sr.sr_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG; - sr.sr_information_rel8.pucch_index = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex; + sr.sr_information_rel8.pucch_index = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex; LOG_D(MAC, "REL8 PUCCH INDEX:%d\n", sr.sr_information_rel8.pucch_index); } @@ -401,7 +403,7 @@ schedule_SR (module_id_t module_idP, } else { ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].pdu_type = NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE; ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG; - ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; + ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti; ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel11.tl.tag = 0; ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel13.tl.tag = 0; ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.sr_information = sr; @@ -416,20 +418,20 @@ schedule_SR (module_id_t module_idP, void check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, frame_t frameP, sub_frame_t subframeP) { - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; nfapi_dl_config_request_t *DL_req = &RC.mac[module_idP]->DL_req[0]; uint16_t rnti = UE_RNTI(module_idP, UE_id); COMMON_channels_t *cc = RC.mac[module_idP]->common_channels; // check uplink failure - if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 0) && - (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) { - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 1) + if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 0) && + (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) { + if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer == 1) LOG_I(MAC, "UE %d rnti %x: UL Failure timer %d \n", UE_id, rnti, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer); - if (UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) { - UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1; + if (UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) { + UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1; // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe) nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[DL_req[CC_id].dl_config_request_body.number_pdu]; memset((void *) dl_config_pdu, 0,sizeof(nfapi_dl_config_request_pdu_t)); @@ -438,7 +440,7 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = get_aggregation(get_bw_index(module_idP, CC_id), - UE_list->UE_sched_ctrl[UE_id]. + UE_info->UE_sched_ctrl[UE_id]. dl_cqi[CC_id], format1A); dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications @@ -454,22 +456,22 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, LOG_D(MAC, "UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n", UE_id, rnti, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer, + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer, dl_config_pdu->dci_dl_pdu. dci_dl_pdu_rel8.resource_block_coding); } else { // ra_pdcch_sent==1 LOG_D(MAC, "UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n", UE_id, rnti, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer); - if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer % 80) == 0) UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0; // resend every 8 frames + if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer % 80) == 0) UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0; // resend every 8 frames } - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++; + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer++; // check threshold - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 4000) { + if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 4000) { // note: probably ul_failure_timer should be less than UE radio link failure time(see T310/N310/N311) if (NODE_IS_DU(RC.rrc[module_idP]->node_type)) { MessageDef *m = itti_alloc_new_message(TASK_MAC_ENB, F1AP_UE_CONTEXT_RELEASE_REQ); @@ -491,17 +493,17 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, rnti); } - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; - UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 1; + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer = 0; + UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync = 1; } } // ul_failure_timer>0 - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer++; + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer++; - if((U_PLANE_INACTIVITY_VALUE != 0) && (UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer > (U_PLANE_INACTIVITY_VALUE * 10))) { + if((U_PLANE_INACTIVITY_VALUE != 0) && (UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer > (U_PLANE_INACTIVITY_VALUE * 10))) { LOG_D(MAC,"UE %d rnti %x: U-Plane Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti); mac_eNB_rrc_uplane_failure(module_idP,CC_id,frameP,subframeP,rnti); - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; }// time > 60s } @@ -565,7 +567,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, int CC_id = 0; int UE_id = -1; eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &(eNB->UE_list); + UE_info_t *UE_info = &(eNB->UE_info); COMMON_channels_t *cc = eNB->common_channels; UE_sched_ctrl_t *UE_scheduling_control = NULL; start_meas(&(eNB->eNB_scheduler)); @@ -584,16 +586,16 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, /* Refresh UE list based on UEs dropped by PHY in previous subframe */ for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id]) { + if (UE_info->active[UE_id]) { rnti = UE_RNTI(module_idP, UE_id); CC_id = UE_PCCID(module_idP, UE_id); - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); + UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); if (((frameP & 127) == 0) && (subframeP == 0)) { LOG_I(MAC,"UE rnti %x : %s, PHR %d dB DL CQI %d PUSCH SNR %d PUCCH SNR %d\n", rnti, UE_scheduling_control->ul_out_of_sync == 0 ? "in synch" : "out of sync", - UE_list->UE_template[CC_id][UE_id].phr_info, + UE_info->UE_template[CC_id][UE_id].phr_info, UE_scheduling_control->dl_cqi[CC_id], (5 * UE_scheduling_control->pusch_snr[CC_id] - 640) / 10, (5 * UE_scheduling_control->pucch1_snr[CC_id] - 640) / 10); @@ -601,7 +603,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, RC.eNB[module_idP][CC_id]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = -63; - if (UE_id == UE_list->head) { + if (UE_id == UE_info->list.head) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR, RC.eNB[module_idP][CC_id]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP]); } @@ -735,7 +737,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, * here for the current subframe. The variable 'UE_scheduling_control->in_active_time' should be updated * ONLY here. The variable can then be used for testing the actual state of the UE for scheduling purpose. */ - UE_template = &(UE_list->UE_template[CC_id][UE_id]); + UE_template = &(UE_info->UE_template[CC_id][UE_id]); /* (a)synchronous HARQ processes handling for Active Time */ for (int harq_process_id = 0; harq_process_id < 8; harq_process_id++) { @@ -981,7 +983,9 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, /* Allocate CCEs for good after scheduling is done */ for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { if (cc[CC_id].tdd_Config == NULL || !(is_UL_sf(&cc[CC_id],subframeP))) { - allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2); + int rc = allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2); + if (rc < 0) + LOG_E(MAC, "%s() %4d.%d ERROR ALLOCATING CCEs\n", __func__, frameP, subframeP); } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c index fb765e6dac..d1365b9ac3 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c @@ -587,7 +587,7 @@ generate_Msg4(module_id_t module_idP, { eNB_MAC_INST *mac = RC.mac[module_idP]; COMMON_channels_t *cc = mac->common_channels; - UE_list_t *UE_list = &(mac->UE_list); + UE_info_t *UE_info = &mac->UE_info; int16_t rrc_sdu_length = 0; uint16_t msg4_padding = 0; uint16_t msg4_post_padding = 0; @@ -831,7 +831,7 @@ generate_Msg4(module_id_t module_idP, dl_req_body->number_pdu++; ra->state = WAITMSG4ACK; lcid = 0; - UE_list->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = 0; + UE_info->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = 0; msg4_header = 1 + 6 + 1; // CR header, CR CE, SDU header AssertFatal((ra->msg4_TBsize - ra->msg4_rrc_sdu_length - msg4_header)>=0, "msg4_TBS %d is too small, change mcs to increase by %d bytes\n",ra->msg4_TBsize,ra->msg4_rrc_sdu_length+msg4_header-ra->msg4_TBsize); @@ -848,7 +848,7 @@ generate_Msg4(module_id_t module_idP, module_idP, CC_idP, frameP, subframeP, ra->msg4_TBsize, ra->msg4_rrc_sdu_length, msg4_header, msg4_padding, msg4_post_padding); DevAssert (UE_id != UE_INDEX_INVALID); // FIXME not sure how to gracefully return // CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0] - offset = generate_dlsch_header ((unsigned char *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], 1, //num_sdus + offset = generate_dlsch_header ((unsigned char *) mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], 1, //num_sdus (unsigned short *) &ra->msg4_rrc_sdu_length, // &lcid, // sdu_lcid 255, // no drx @@ -856,7 +856,7 @@ generate_Msg4(module_id_t module_idP, ra->cont_res_id, // contention res id msg4_padding, // no padding msg4_post_padding); - memcpy ((void *) &mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0][(unsigned char) offset], &cc[CC_idP].CCCH_pdu.payload[0], ra->msg4_rrc_sdu_length); + memcpy ((void *) &mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0][(unsigned char) offset], &cc[CC_idP].CCCH_pdu.payload[0], ra->msg4_rrc_sdu_length); // DL request mac->TX_req[CC_idP].sfn_sf = (frameP << 4) + subframeP; TX_req = &mac->TX_req[CC_idP].tx_request_body.tx_pdu_list[mac->TX_req[CC_idP].tx_request_body.number_of_pdus]; @@ -864,7 +864,7 @@ generate_Msg4(module_id_t module_idP, TX_req->pdu_index = mac->pdu_index[CC_idP]++; TX_req->num_segments = 1; TX_req->segments[0].segment_length = ra->msg4_TBsize; - TX_req->segments[0].segment_data = mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0]; + TX_req->segments[0].segment_data = mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0]; mac->TX_req[CC_idP].tx_request_body.number_of_pdus++; // Program ACK/NAK for Msg4 PDSCH int absSF = (frameP * 10) + subframeP; @@ -899,8 +899,8 @@ generate_Msg4(module_id_t module_idP, ul_req_body->number_of_pdus++; T (T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT (module_idP), T_INT (CC_idP), T_INT (ra->rnti), T_INT (frameP), T_INT (subframeP), - T_INT (0 /*harq_pid always 0? */ ), T_BUFFER (&mac->UE_list.DLSCH_pdu[CC_idP][0][UE_id].payload[0], ra->msg4_TBsize)); - trace_pdu (DIRECTION_DOWNLINK, (uint8_t *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], + T_INT (0 /*harq_pid always 0? */ ), T_BUFFER (&mac->UE_info.DLSCH_pdu[CC_idP][0][UE_id].payload[0], ra->msg4_TBsize)); + trace_pdu (DIRECTION_DOWNLINK, (uint8_t *) mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], ra->msg4_rrc_sdu_length, UE_id, 3, UE_RNTI (module_idP, UE_id), mac->frame, mac->subframe, 0, 0); @@ -963,10 +963,10 @@ generate_Msg4(module_id_t module_idP, 1, // tpc, none getRIV(N_RB_DL, first_rb, 4), // resource_block_coding ra->msg4_mcs, // mcs - 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], + 1 - UE_info->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], 0, // rv 0); // vrb_flag - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid] = 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid]; + UE_info->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid] = 1 - UE_info->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid]; LOG_D(MAC, "Frame %d, subframe %d: Msg4 DCI pdu_num %d (rnti %x,rnti_type %d,harq_pid %d, resource_block_coding (%p) %d\n", frameP, subframeP, dl_req_body->number_pdu, @@ -1000,7 +1000,7 @@ generate_Msg4(module_id_t module_idP, lcid = 0; // put HARQ process round to 0 ra->harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - UE_list->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = 0; + UE_info->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = 0; if ((ra->msg4_TBsize - rrc_sdu_length - msg4_header) <= 2) { msg4_padding = ra->msg4_TBsize - rrc_sdu_length - msg4_header; @@ -1018,7 +1018,7 @@ generate_Msg4(module_id_t module_idP, DevAssert(UE_id != UE_INDEX_INVALID); // FIXME not sure how to gracefully return // CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0] int num_sdus = rrc_sdu_length > 0 ? 1 : 0; - offset = generate_dlsch_header((unsigned char *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], + offset = generate_dlsch_header((unsigned char *) mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], num_sdus, //num_sdus (unsigned short *) &rrc_sdu_length, // &lcid, // sdu_lcid @@ -1027,10 +1027,14 @@ generate_Msg4(module_id_t module_idP, ra->cont_res_id, // contention res id msg4_padding, // no padding msg4_post_padding); - memcpy((void *) &mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], + memcpy((void *) &mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], &cc[CC_idP].CCCH_pdu.payload[0], rrc_sdu_length); // DLSCH Config - fill_nfapi_dlsch_config(mac, dl_req_body, ra->msg4_TBsize, mac->pdu_index[CC_idP], ra->rnti, 2, // resource_allocation_type : format 1A/1B/1D + fill_nfapi_dlsch_config(&dl_req_body->dl_config_pdu_list[dl_req_body->number_pdu], + ra->msg4_TBsize, + mac->pdu_index[CC_idP], + ra->rnti, + 2, // resource_allocation_type : format 1A/1B/1D 0, // virtual_resource_block_assignment_flag : localized getRIV(N_RB_DL, first_rb, 4), // resource_block_coding : RIV, 4 PRB 2, // modulation: QPSK @@ -1049,6 +1053,7 @@ generate_Msg4(module_id_t module_idP, (cc->p_eNB == 1) ? 1 : 2, // transmission mode 1, // num_bf_prb_per_subband 1); // num_bf_vector + dl_req_body->number_pdu++; LOG_D(MAC, "Filled DLSCH config, pdu number %d, non-dci pdu_index %d\n", dl_req_body->number_pdu, mac->pdu_index[CC_idP]); @@ -1058,7 +1063,7 @@ generate_Msg4(module_id_t module_idP, (frameP * 10) + subframeP, rrc_sdu_length+offset, mac->pdu_index[CC_idP], - mac->UE_list. + mac->UE_info. DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0]); mac->pdu_index[CC_idP]++; dl_req->sfn_sf = mac->TX_req[CC_idP].sfn_sf; @@ -1074,11 +1079,11 @@ generate_Msg4(module_id_t module_idP, T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_idP), T_INT(ra->rnti), T_INT(frameP), T_INT(subframeP), T_INT(0 /*harq_pid always 0? */ ), - T_BUFFER(&mac->UE_list.DLSCH_pdu[CC_idP][0][UE_id]. + T_BUFFER(&mac->UE_info.DLSCH_pdu[CC_idP][0][UE_id]. payload[0], ra->msg4_TBsize)); trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) mac-> - UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], + UE_info.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], rrc_sdu_length, UE_id, WS_C_RNTI, UE_RNTI(module_idP, UE_id), mac->frame, mac->subframe, 0, 0); @@ -1116,14 +1121,14 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, int first_rb; int N_RB_DL; nfapi_dl_config_request_pdu_t *dl_config_pdu; - UE_list_t *UE_list = &mac->UE_list; + UE_info_t *UE_info = &mac->UE_info; nfapi_dl_config_request_t *dl_req; nfapi_dl_config_request_body_t *dl_req_body; int round; // check HARQ status and retransmit if necessary UE_id = find_UE_id(module_idP, ra->rnti); AssertFatal(UE_id >= 0, "Can't find UE for t-crnti\n"); - round = UE_list->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid]; + round = UE_info->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid]; vrb_map = cc[CC_idP].vrb_map; dl_req = &mac->DL_req[CC_idP]; dl_req_body = &dl_req->dl_config_request_body; @@ -1156,7 +1161,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, 1, // tpc, none getRIV(N_RB_DL, first_rb, 4), // resource_block_coding ra->msg4_mcs, // mcs - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], + UE_info->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], round & 3, // rv 0); // vrb_flag @@ -1173,7 +1178,8 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, // DLSCH Config //DJP - fix this pdu_index = -1 LOG_D(MAC, "check_Msg4_retransmission() before fill_nfapi_dlsch_config() with pdu_index = -1 \n"); - fill_nfapi_dlsch_config(mac, dl_req_body, ra->msg4_TBsize, + fill_nfapi_dlsch_config(&dl_req_body->dl_config_pdu_list[dl_req_body->number_pdu], + ra->msg4_TBsize, -1 /* retransmission, no pdu_index */ , ra->rnti, 2, // resource_allocation_type : format 1A/1B/1D @@ -1195,6 +1201,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, (cc->p_eNB == 1) ? 1 : 2, // transmission mode 1, // num_bf_prb_per_subband 1); // num_bf_vector + dl_req_body->number_pdu++; if(RC.mac[module_idP]->scheduler_mode == SCHED_MODE_FAIR_RR) { set_dl_ue_select_msg4(CC_idP, 4, UE_id, ra->rnti); @@ -1226,8 +1233,8 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:IDLE\n", module_idP, frameP, subframeP); UE_id = find_UE_id(module_idP, ra->rnti); DevAssert(UE_id != -1); - mac->UE_list.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured = TRUE; - mac->UE_list.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].pusch_repetition_levels=ra->pusch_repetition_levels; + mac->UE_info.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured = TRUE; + mac->UE_info.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].pusch_repetition_levels=ra->pusch_repetition_levels; cancel_ra_proc(module_idP, CC_idP, frameP, ra->rnti); } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index eba4bdcee9..7621994ab2 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -86,31 +86,6 @@ add_ue_dlsch_info(module_id_t module_idP, return; } -//------------------------------------------------------------------------------ -int -schedule_next_dlue(module_id_t module_idP, - int CC_id, - sub_frame_t subframeP) -//------------------------------------------------------------------------------ -{ - int next_ue; - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; - - for (next_ue = UE_list->head; next_ue >= 0; next_ue = UE_list->next[next_ue]) { - if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_WAITING) { - return next_ue; - } - } - - for (next_ue = UE_list->head; next_ue >= 0; next_ue = UE_list->next[next_ue]) { - if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_BUFFERED) { - eNB_dlsch_info[module_idP][CC_id][next_ue].status = S_DL_WAITING; - } - } - - return (-1); //next_ue; -} - //------------------------------------------------------------------------------ int generate_dlsch_header(unsigned char *mac_header, @@ -317,12 +292,12 @@ set_ul_DAI(int module_idP, //------------------------------------------------------------------------------ { eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; unsigned char DAI; COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; if (cc->tdd_Config != NULL) { //TDD - DAI = (UE_list->UE_template[CC_idP][UE_idP].DAI - 1) & 3; + DAI = (UE_info->UE_template[CC_idP][UE_idP].DAI - 1) & 3; LOG_D(MAC, "[eNB %d] CC_id %d Frame %d, subframe %d: DAI %d for UE %d\n", module_idP, CC_idP, @@ -341,20 +316,20 @@ set_ul_DAI(int module_idP, switch (subframeP) { case 0: case 1: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI; break; case 4: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI; break; case 5: case 6: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; break; case 9: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; break; } @@ -362,30 +337,30 @@ set_ul_DAI(int module_idP, case 2: // if ((subframeP==3)||(subframeP==8)) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul = DAI; break; case 3: //if ((subframeP==6)||(subframeP==8)||(subframeP==0)) { // LOG_D(MAC,"schedule_ue_spec: setting UL DAI to %d for subframeP %d => %d\n",DAI,subframeP, ((subframeP+8)%10)>>1); - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul[((subframeP+8)%10)>>1] = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul[((subframeP+8)%10)>>1] = DAI; //} switch (subframeP) { case 5: case 6: case 1: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; break; case 7: case 8: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; break; case 9: case 0: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI; break; default: @@ -396,17 +371,17 @@ set_ul_DAI(int module_idP, case 4: // if ((subframeP==8)||(subframeP==9)) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul = DAI; break; case 5: // if (subframeP==8) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul = DAI; break; case 6: // if ((subframeP==1)||(subframeP==4)||(subframeP==6)||(subframeP==9)) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul = DAI; break; default: @@ -417,20 +392,129 @@ set_ul_DAI(int module_idP, return; } +void ue_rrc_release(rnti_t rnti) { + if(rrc_release_info.num_UEs == 0 || rlc_am_mui.rrc_mui_num == 0) { + return; + } + + while(pthread_mutex_trylock(&rrc_release_freelist)) { + /* spin... */ + } + + uint16_t release_total = 0; + + for (uint16_t n = 0; n < NUMBER_OF_UE_MAX; n++) { + RRC_release_ctrl_t *release_ctrl = &rrc_release_info.RRC_release_ctrl[n]; + if(release_ctrl->flag == 0) + continue; + + release_total++; + if(release_ctrl->flag == 1 && release_ctrl->rnti == rnti) { + for(uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { + release_ctrl->flag = 3; + LOG_D(MAC, + "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3\n", + n, rnti, rlc_am_mui.rrc_mui[mui_num], mui_num); + break; + } + } + } + + if(release_ctrl->flag == 2 && release_ctrl->rnti == rnti) { + for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { + release_ctrl->flag = 4; + LOG_D(MAC, "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4\n", + n, + rnti, + rlc_am_mui.rrc_mui[mui_num], + mui_num); + break; + } + } + } + + if(release_total >= rrc_release_info.num_UEs) + break; + } + + pthread_mutex_unlock(&rrc_release_freelist); +} + +void check_ra_rnti_mui(module_id_t mod_id, int CC_id, frame_t f, sub_frame_t sf, rnti_t rnti) { + LTE_TDD_Config_t *tdd_config = RC.mac[mod_id]->common_channels[CC_id].tdd_Config; + int harq_pid = frame_subframe2_dl_harq_pid(tdd_config, f, sf); + RA_t *ra = &RC.mac[mod_id]->common_channels[CC_id].ra[0]; + for (uint8_t ra_ii = 0; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) { + if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) { + for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if (ra->crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) { + ra->crnti_harq_pid = harq_pid; + ra->state = MSGCRNTI_ACK; + break; + } + } + } + } +} + //------------------------------------------------------------------------------ void schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) { - int i = 0; - slice_info_t *sli = &RC.mac[module_idP]->slice_info; - memset(sli->rballoc_sub, 0, sizeof(sli->rballoc_sub)); + if (is_pmch_subframe(frameP, subframeP, &RC.eNB[module_idP][0]->frame_parms)) + return; - for (i = 0; i < sli->n_dl; i++) { - // Run each enabled slice-specific schedulers one by one - sli->dl[i].sched_cb(module_idP, - i, - frameP, - subframeP, - mbsfn_flag/*, dl_info*/); + for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { + // for TDD: check that we have to act here, otherwise skip + COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id]; + if (cc->tdd_Config) { + int tdd_sfa = cc->tdd_Config->subframeAssignment; + + switch (subframeP) { + case 0: + // always continue + break; + + case 1: + case 2: + continue; + + case 3: + if (tdd_sfa != 2 && tdd_sfa != 5) + continue; + break; + + case 4: + if (tdd_sfa != 1 && tdd_sfa != 2 && tdd_sfa != 4 && tdd_sfa != 5) + continue; + break; + + case 5: + break; + + case 6: + case 7: + if (tdd_sfa != 3 && tdd_sfa != 4 && tdd_sfa != 5) + continue; + break; + + case 8: + if (tdd_sfa != 2 && tdd_sfa != 3 && tdd_sfa != 4 && tdd_sfa != 5) + continue; + break; + + case 9: + if (tdd_sfa == 0) + continue; + break; + } + } + + if (mbsfn_flag[CC_id] != 0) + continue; + + schedule_ue_spec(module_idP, CC_id, frameP, subframeP); } } @@ -454,138 +538,35 @@ void getRepetition(UE_TEMPLATE *pue_template,unsigned int *maxRep, unsigned int */ void schedule_ue_spec(module_id_t module_idP, - int slice_idxP, + int CC_id, frame_t frameP, - sub_frame_t subframeP, - int *mbsfn_flag) + sub_frame_t subframeP) //------------------------------------------------------------------------------ { - int CC_id; - int UE_id; - int aggregation; - mac_rlc_status_resp_t rlc_status; - int ta_len = 0; - unsigned char sdu_lcids[NB_RB_MAX]; - int lcid, offset, num_sdus = 0; - int nb_rb, nb_rb_temp, nb_available_rb; - uint16_t sdu_lengths[NB_RB_MAX]; - int TBS, j, padding = 0, post_padding = 0; - rnti_t rnti; unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; - int round_DL = 0; - int harq_pid = 0; - uint16_t release_num; - uint8_t ra_ii; - eNB_UE_STATS *eNB_UE_stats = NULL; - UE_TEMPLATE *ue_template = NULL; - eNB_STATS *eNB_stats = NULL; - RRC_release_ctrl_t *release_ctrl = NULL; - DLSCH_PDU *dlsch_pdu = NULL; - RA_t *ra = NULL; - int sdu_length_total = 0; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; - int continue_flag = 0; - int32_t snr, target_snr; - int tpc = 1; - UE_sched_ctrl_t *ue_sched_ctrl; - int mcs; - int i; - int min_rb_unit[NFAPI_CC_MAX]; - int N_RB_DL[NFAPI_CC_MAX]; - int total_nb_available_rb[NFAPI_CC_MAX]; - int N_RBG[NFAPI_CC_MAX]; - nfapi_dl_config_request_body_t *dl_req; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - int tdd_sfa; - int ta_update; - int header_length_last; - int header_length_total; - rrc_eNB_ue_context_t *ue_contextP = NULL; - int nb_mac_CC = RC.nb_mac_CC[module_idP]; - long dl_Bandwidth; - - if(is_pmch_subframe(frameP,subframeP,&RC.eNB[module_idP][0]->frame_parms)){ - //LOG_E(MAC,"Frame[%d] SF:%d This SF should not be allocated\n",frameP,subframeP); - return ; - } - + UE_info_t *UE_info = &eNB->UE_info; + const int dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; + const int N_RB_DL = to_prb(dl_Bandwidth); + const int N_RBG = to_rbg(eNB->common_channels[CC_id].mib->message.dl_Bandwidth); + int total_nb_available_rb = N_RB_DL; + nfapi_dl_config_request_body_t *dl_req = &eNB->DL_req[CC_id].dl_config_request_body; start_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN); - // for TDD: check that we have to act here, otherwise return - if (cc[0].tdd_Config) { - tdd_sfa = cc[0].tdd_Config->subframeAssignment; + for (int i = 0; i < N_RB_DL; i++) + if (cc[CC_id].vrb_map[i] != 0) + total_nb_available_rb--; - switch (subframeP) { - case 0: - // always continue - break; - - case 1: - case 2: - return; - - case 3: - if (tdd_sfa != 2 && tdd_sfa != 5) - return; - - break; - - case 4: - if (tdd_sfa != 1 && tdd_sfa != 2 && tdd_sfa != 4 && tdd_sfa != 5) - return; - - break; - - case 5: - break; - - case 6: - case 7: - if (tdd_sfa != 3 && tdd_sfa != 4 && tdd_sfa != 5) - return; - - break; - - case 8: - if (tdd_sfa != 2 && tdd_sfa != 3 && tdd_sfa != 4 && tdd_sfa != 5) - return; - - break; - - case 9: - if (tdd_sfa == 0) - return; - - break; - } - } - - aggregation = 2; - - for (CC_id = 0, eNB_stats = &eNB->eNB_stats[0]; CC_id < nb_mac_CC; CC_id++, eNB_stats++) { - dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; - N_RB_DL[CC_id] = to_prb(dl_Bandwidth); - min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); - // get number of PRBs less those used by common channels - total_nb_available_rb[CC_id] = N_RB_DL[CC_id]; - - for (i = 0; i < N_RB_DL[CC_id]; i++) - if (cc[CC_id].vrb_map[i] != 0) - total_nb_available_rb[CC_id]--; - - N_RBG[CC_id] = to_rbg(dl_Bandwidth); - // store the global enb stats: - eNB_stats->num_dlactive_UEs = UE_list->num_UEs; - eNB_stats->available_prbs = total_nb_available_rb[CC_id]; - eNB_stats->total_available_prbs += total_nb_available_rb[CC_id]; - eNB_stats->dlsch_bytes_tx = 0; - eNB_stats->dlsch_pdus_tx = 0; - } + // store the global enb stats: + eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_info->num_UEs; + eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb; + eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb; + eNB->eNB_stats[CC_id].dlsch_bytes_tx = 0; + eNB->eNB_stats[CC_id].dlsch_pdus_tx = 0; // CALLING Pre_Processor for downlink scheduling // (Returns estimation of RBs required by each UE and the allocation on sub-band) @@ -593,1259 +574,626 @@ schedule_ue_spec(module_id_t module_idP, VCD_FUNCTION_IN); start_meas(&eNB->schedule_dlsch_preprocessor); dlsch_scheduler_pre_processor(module_idP, - slice_idxP, + CC_id, frameP, - subframeP, - mbsfn_flag, - eNB->slice_info.rballoc_sub); + subframeP); stop_meas(&eNB->schedule_dlsch_preprocessor); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT); - if (RC.mac[module_idP]->slice_info.interslice_share_active) { - dlsch_scheduler_interslice_multiplexing(module_idP, - frameP, - subframeP, - eNB->slice_info.rballoc_sub); - /* the interslice multiplexing re-sorts the UE_list for the slices it tries - * to multiplex, so we need to sort it for the current slice again */ - sort_UEs(module_idP, - slice_idxP, - frameP, - subframeP); - } + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", + CC_id, + UE_id); + UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id]; + eNB_UE_STATS *eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; + const rnti_t rnti = ue_template->rnti; - for (CC_id = 0; CC_id < nb_mac_CC; CC_id++) { - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", - CC_id); - dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + // If TDD + if (cc[CC_id].tdd_Config != NULL) { //TDD + set_ue_dai(subframeP, + UE_id, + CC_id, + cc[CC_id].tdd_Config->subframeAssignment, + UE_info); + // update UL DAI after DLSCH scheduling + set_ul_DAI(module_idP, + UE_id, + CC_id, + frameP, + subframeP); + } - if (mbsfn_flag[CC_id] > 0) + ue_rrc_release(rnti); + check_ra_rnti_mui(module_idP, CC_id, frameP, subframeP, rnti); + + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) { // no RBs allocated + LOG_D(MAC, "%d.%d: no RBs allocated for UE %d on CC_id %d\n", + frameP, + subframeP, + UE_id, + CC_id); continue; + } - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", - CC_id, - UE_id); - continue_flag = 0; // reset the flag to allow allocation for the remaining UEs - rnti = UE_RNTI(module_idP, UE_id); - ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; - ue_template = &UE_list->UE_template[CC_id][UE_id]; - - if (ue_template->rach_resource_type > 0) { - continue_flag = 1; + int dci_dl_pdu_idx = ue_sched_ctrl->pre_dci_dl_pdu_idx; + if (dci_dl_pdu_idx < 0) { + dci_dl_pdu_idx = CCE_try_allocate_dlsch( + module_idP, CC_id, subframeP, UE_id, ue_sched_ctrl->dl_cqi[CC_id]); + if (dci_dl_pdu_idx < 0) { + LOG_W(MAC, "%d.%d: Dropping Allocation for RNTI 0x%04x/UE %d\n", + frameP, + subframeP, + rnti, + UE_id); + continue; } + } - if (&(UE_list->eNB_UE_stats[CC_id][UE_id]) == NULL) { - LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n"); - continue_flag = 1; - } else { - eNB_UE_stats = &(UE_list->eNB_UE_stats[CC_id][UE_id]); - } + /* verify it is the right UE */ + nfapi_dl_config_request_pdu_t *dci = &dl_req->dl_config_pdu_list[dci_dl_pdu_idx]; + nfapi_dl_config_request_pdu_t *dlsch = &dl_req->dl_config_pdu_list[dci_dl_pdu_idx + 1]; + if (dci->pdu_type != NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE + || dci->dci_dl_pdu.dci_dl_pdu_rel8.rnti != rnti + || dlsch->pdu_type != NFAPI_DL_CONFIG_DLSCH_PDU_TYPE + || dlsch->dlsch_pdu.dlsch_pdu_rel8.rnti != rnti) { + LOG_E(MAC, "illegal dl_config_pdu_list index %d for UE %d/RNTI %04x\n", + dci_dl_pdu_idx, + UE_id, + rnti); + continue; + } - if (continue_flag != 1) { - switch (get_tmode(module_idP, - CC_id, - UE_id)) { - case 1: - case 2: - case 7: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - break; + const int harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, + frameP, + subframeP); + const int round_DL = ue_sched_ctrl->round[CC_id][harq_pid]; + eNB_UE_stats->crnti = rnti; + eNB_UE_stats->rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); + eNB_UE_stats->harq_pid = harq_pid; + eNB_UE_stats->harq_round = round_DL; - case 3: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format2A); - break; + if (eNB_UE_stats->rrc_status < RRC_RECONFIGURED) { + ue_sched_ctrl->uplane_inactivity_timer = 0; + } - default: - AssertFatal(1==0,"Unsupported transmission mode %d\n", get_tmode(module_idP, CC_id, UE_id)); - aggregation = 2; - break; - } - } + LOG_D(MAC, "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", + module_idP, + frameP, + UE_id, + CC_id, + rnti, + harq_pid, + round_DL, + ue_sched_ctrl->pre_nb_available_rbs[CC_id], + ue_sched_ctrl->dl_cqi[CC_id], + eNB_UE_stats->dlsch_mcs1, + eNB_UE_stats->rrc_status); - /* if (continue_flag != 1 */ - if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0 || // no RBs allocated - CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - aggregation, - rnti)) { - LOG_D(MAC, "[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", + /* Process retransmission */ + if (round_DL != 8) { + // get freq_allocation + const int nb_rb = ue_template->nb_rb[harq_pid]; + int TBS = get_TBS_DL(ue_template->oldmcs1[harq_pid], nb_rb); + const uint32_t rbc = allocate_prbs_sub( + nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); + + if (nb_rb > ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { + LOG_D(MAC, + "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", module_idP, frameP, + CC_id, + UE_id); + continue; + } + + /* CDRX */ + ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + + if (ue_sched_ctrl->cdrx_configured) { + ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + + /* + * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. + */ + if (harq_pid == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); + } + } + + if (cc[CC_id].tdd_Config != NULL) { + ue_template->DAI++; + update_ul_dci(module_idP, + CC_id, + rnti, + ue_template->DAI, + subframeP); + LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", + CC_id, + subframeP, UE_id, - CC_id); - continue_flag = 1; //to next user (there might be rbs availiable for other UEs in TM5 + ue_template->DAI); } - // If TDD - if (cc[CC_id].tdd_Config != NULL) { //TDD - set_ue_dai(subframeP, - UE_id, - CC_id, - cc[CC_id].tdd_Config->subframeAssignment, - UE_list); - // update UL DAI after DLSCH scheduling - set_ul_DAI(module_idP, - UE_id, - CC_id, - frameP, - subframeP); - } - - if (continue_flag == 1) { - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_NONE, - rnti); - continue; - } - - nb_available_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, - frameP, - subframeP); - round_DL = ue_sched_ctrl->round[CC_id][harq_pid]; - eNB_UE_stats->crnti = rnti; - eNB_UE_stats->rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); - eNB_UE_stats->harq_pid = harq_pid; - eNB_UE_stats->harq_round = round_DL; - - if (eNB_UE_stats->rrc_status < RRC_RECONFIGURED) { - ue_sched_ctrl->uplane_inactivity_timer = 0; - } - - if (eNB_UE_stats->rrc_status < RRC_CONNECTED) { - LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n", UE_id); - continue; - } - - header_length_total = 0; - sdu_length_total = 0; - num_sdus = 0; - - /* - DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) || - (eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)), - eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE); - */ - if (NFAPI_MODE != NFAPI_MONOLITHIC) { - eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]]; - } else { // this operation is also done in the preprocessor - eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, - eNB->slice_info.dl[slice_idxP].maxmcs); // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); - } - - // Store stats - // eNB_UE_stats->dl_cqi= eNB_UE_stats->dl_cqi; - - // Initializing the rb allocation indicator for each UE - for (j = 0; j < N_RBG[CC_id]; j++) { - ue_template->rballoc_subband[harq_pid][j] = 0; - } - - LOG_D(MAC, "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", - module_idP, - frameP, - UE_id, - CC_id, - rnti, - harq_pid, - round_DL, - nb_available_rb, - ue_sched_ctrl->dl_cqi[CC_id], - eNB_UE_stats->dlsch_mcs1, - eNB_UE_stats->rrc_status); - - /* Process retransmission */ - if (round_DL != 8) { - // get freq_allocation - nb_rb = ue_template->nb_rb[harq_pid]; - TBS = get_TBS_DL(ue_template->oldmcs1[harq_pid], - nb_rb); - - if (nb_rb <= nb_available_rb) { - /* CDRX */ - ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer - - if (ue_sched_ctrl->cdrx_configured) { - ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission - - /* - * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. - */ - if (harq_pid == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); - } - } - - if (cc[CC_id].tdd_Config != NULL) { - ue_template->DAI++; - update_ul_dci(module_idP, - CC_id, - rnti, - ue_template->DAI, - subframeP); - LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", - CC_id, - subframeP, - UE_id, - ue_template->DAI); - } - - if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - for (j = 0; j < N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { - if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { - if (ue_template->rballoc_subband[harq_pid][j]) - LOG_W(MAC, "WARN: rballoc_subband not free for retrans?\n"); - - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - nb_rb_temp -= min_rb_unit[CC_id]; - - if ((j == N_RBG[CC_id] - 1) && (N_RB_DL[CC_id] == 25 || N_RB_DL[CC_id] == 50)) - nb_rb_temp++; - } - - j++; - } - } - - nb_available_rb -= nb_rb; - - switch (get_tmode(module_idP, CC_id, UE_id)) { - case 1: - case 2: - case 7: - default: - LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", - rnti); - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void *) dl_config_pdu, - 0, - sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = - get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI: see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // Don't adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ue_template->oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = ue_template->oldmcs1[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round_DL & 3; - - // TDD - if (cc[CC_id].tdd_Config != NULL) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; - LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - round_DL, - ue_template->DAI - 1, - ue_template->oldmcs1[harq_pid]); - } else { - LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - round_DL, - ue_template->oldmcs1[harq_pid]); - } - - if (!CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - rnti)) { - dl_req->number_dci++; - dl_req->number_pdu++; - dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; - eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; - eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - fill_nfapi_dlsch_config(eNB, - dl_req, - TBS, - -1, // retransmission, no pdu_index - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later - getQm(ue_template->oldmcs1[harq_pid]), - round_DL & 3, // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0); // number of beamforming vectors, not used here - LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", - eNB->pdu_index[CC_id], - round_DL); - program_dlsch_acknak(module_idP, - CC_id, - UE_id, - frameP, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - // No TX request for retransmission (check if null request for FAPI) - } else { - LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n", - frameP, - subframeP, - UE_id, - rnti); - } - } - - add_ue_dlsch_info(module_idP, - CC_id, UE_id, - subframeP, - S_DL_SCHEDULED, - rnti); - //eNB_UE_stats->dlsch_trials[round]++; - eNB_UE_stats->num_retransmission += 1; - eNB_UE_stats->rbs_used_retx = nb_rb; - eNB_UE_stats->total_rbs_used_retx += nb_rb; - eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; - } else { - LOG_D(MAC, - "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", - module_idP, - frameP, - CC_id, - UE_id); - } - } else { - /* This is a potentially new SDU opportunity */ - rlc_status.bytes_in_buffer = 0; - // Now check RLC information to compute number of required RBs - // get maximum TBS size for RLC request - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_available_rb); - - // add the length for all the control elements (timing adv, drx, etc) : header + payload - - if (ue_sched_ctrl->ta_timer == 0) { - ta_update = ue_sched_ctrl->ta_update; - - /* if we send TA then set timer to not send it for a while */ - if (ta_update != 31) { - ue_sched_ctrl->ta_timer = 20; - } - - /* reset ta_update */ - ue_sched_ctrl->ta_update = 31; - } else { - ta_update = 31; - } - - ta_len = (ta_update != 31) ? 2 : 0; - - // RLC data on DCCH - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 - ); - sdu_lengths[0] = 0; - - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP, - frameP, - subframeP, - CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); - sdu_lengths[0] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - TBS, //not used - (char *)&dlsch_buffer[0], 0, 0 - ); - - if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) { - while(pthread_mutex_trylock(&rrc_release_freelist)) { - /* spin... */ - } - - uint16_t release_total = 0; - - for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0]; - release_num < NUMBER_OF_UE_MAX; - release_num++, release_ctrl++) { - if(release_ctrl->flag > 0) { - release_total++; - } else { - continue; - } - - if(release_ctrl->flag == 1) { - if(release_ctrl->rnti == rnti) { - for(uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { - release_ctrl->flag = 3; - LOG_D(MAC,"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3\n", - release_num, - rnti, - rlc_am_mui.rrc_mui[mui_num], - mui_num); - break; - } - } - } - } - - if(release_ctrl->flag == 2) { - if(release_ctrl->rnti == rnti) { - for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { - release_ctrl->flag = 4; - LOG_D(MAC, "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4\n", - release_num, - rnti, - rlc_am_mui.rrc_mui[mui_num], - mui_num); - break; - } - } - } - } - - if(release_total >= rrc_release_info.num_UEs) - break; - } - - pthread_mutex_unlock(&rrc_release_freelist); - } - - for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) { - if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) { - for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if (ra->crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) { - ra->crnti_harq_pid = harq_pid; - ra->state = MSGCRNTI_ACK; - break; - } - } - } - } - - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(DCCH), - T_INT(sdu_lengths[0])); - LOG_D(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n", - module_idP, - CC_id, - sdu_lengths[0]); - sdu_length_total = sdu_lengths[0]; - sdu_lcids[0] = DCCH; - eNB_UE_stats->lcid_sdu[0] = DCCH; - eNB_UE_stats->sdu_length_tx[DCCH] = sdu_lengths[0]; - eNB_UE_stats->num_pdu_tx[DCCH] += 1; - eNB_UE_stats->num_bytes_tx[DCCH] += sdu_lengths[0]; - header_length_last = 1 + 1 + (sdu_lengths[0] >= 128); - header_length_total += header_length_last; - num_sdus = 1; -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes :", - module_idP, - CC_id, - sdu_lengths[0]); - - for (j = 0; j < sdu_lengths[0]; ++j) { - LOG_T(MAC, "%x ", - dlsch_buffer[j]); - } - - LOG_T(MAC, "\n"); -#endif - } - } - - // RLC data on DCCH1 - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH + 1, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 - ); - // DCCH SDU - sdu_lengths[num_sdus] = 0; - - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP, frameP, CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); - sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, DCCH + 1, - TBS, //not used - (char *) &dlsch_buffer[sdu_length_total], 0, 0 - ); - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(DCCH + 1), - T_INT(sdu_lengths[num_sdus])); - sdu_lcids[num_sdus] = DCCH1; - sdu_length_total += sdu_lengths[num_sdus]; - eNB_UE_stats->lcid_sdu[num_sdus] = DCCH1; - eNB_UE_stats->sdu_length_tx[DCCH1] = sdu_lengths[num_sdus]; - eNB_UE_stats->num_pdu_tx[DCCH1] += 1; - eNB_UE_stats->num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - num_sdus++; -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d][DCCH1] CC_id %d Got %d bytes :", - module_idP, - CC_id, - sdu_lengths[num_sdus]); - - for (j = 0; j < sdu_lengths[num_sdus]; ++j) { - LOG_T(MAC, "%x ", - dlsch_buffer[j]); - } - - LOG_T(MAC, "\n"); -#endif - } - } - - // TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list). - for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { - // TODO: check if the lcid is active - LOG_D(MAC, "[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n", - module_idP, - frameP, - lcid, - TBS, - TBS - ta_len - header_length_total - sdu_length_total - 3); - - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 - ); - - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n", - module_idP, - frameP, - TBS - ta_len - header_length_total - sdu_length_total - 3, - lcid, - header_length_total); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS, //not used - (char *) &dlsch_buffer[sdu_length_total], 0, 0 - ); - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(lcid), - T_INT(sdu_lengths[num_sdus])); - LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", - module_idP, - sdu_lengths[num_sdus], - lcid); - sdu_lcids[num_sdus] = lcid; - sdu_length_total += sdu_lengths[num_sdus]; - eNB_UE_stats->num_pdu_tx[lcid]++; - eNB_UE_stats->lcid_sdu[num_sdus] = lcid; - eNB_UE_stats->sdu_length_tx[lcid] = sdu_lengths[num_sdus]; - eNB_UE_stats->num_bytes_tx[lcid] += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - num_sdus++; - ue_sched_ctrl->uplane_inactivity_timer = 0; - // reset RRC inactivity timer after uplane activity - ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti); - - if (ue_contextP != NULL) { - ue_contextP->ue_context.ue_rrc_inactivity_timer = 1; - } else { - LOG_E(MAC, "[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer\n", - module_idP, - CC_id, - rnti); - } - } // end if (rlc_status.bytes_in_buffer > 0) - } else { // no TBS left - break; // break for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) - } - } - - /* Last header does not have length field */ - if (header_length_total) { - header_length_total -= header_length_last; - header_length_total++; - } - - // there is at least one SDU or TA command - // if (num_sdus > 0 ){ - if (ta_len + sdu_length_total + header_length_total > 0) { - // Now compute number of required RBs for total sdu length - // Assume RAH format 2 - mcs = eNB_UE_stats->dlsch_mcs1; - - if (mcs == 0) { - nb_rb = 4; // don't let the TBS get too small - } else { - nb_rb = min_rb_unit[CC_id]; - } - - TBS = get_TBS_DL(mcs, nb_rb); - - while (TBS < sdu_length_total + header_length_total + ta_len) { - nb_rb += min_rb_unit[CC_id]; // - - if (nb_rb > nb_available_rb) { // if we've gone beyond the maximum number of RBs - // (can happen if N_RB_DL is odd) - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_available_rb); - nb_rb = nb_available_rb; - break; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_rb); - } - - if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - for (j = 0; j < N_RBG[CC_id]; ++j) { // for indicating the rballoc for each sub-band - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { - if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - - if ((j == N_RBG[CC_id] - 1) && ((N_RB_DL[CC_id] == 25) || (N_RB_DL[CC_id] == 50))) { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id] + 1; - } else { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]; - } - } - - j++; - } - } - - // decrease mcs until TBS falls below required length - while ((TBS > sdu_length_total + header_length_total + ta_len) && (mcs > 0)) { - mcs--; - TBS = get_TBS_DL(mcs, - nb_rb); - } - - // if we have decreased too much or we don't have enough RBs, increase MCS - while (TBS < sdu_length_total + header_length_total + ta_len && - ((ue_sched_ctrl->dl_pow_off[CC_id] > 0 && mcs < 28) || (ue_sched_ctrl->dl_pow_off[CC_id] == 0 && mcs <= 15))) { - mcs++; - TBS = get_TBS_DL(mcs, - nb_rb); - } - - LOG_D(MAC, "dlsch_mcs before and after the rate matching = (%d, %d)\n", - eNB_UE_stats->dlsch_mcs1, - mcs); -#ifdef DEBUG_eNB_SCHEDULER - LOG_D(MAC, "[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n", - module_idP, - CC_id, - mcs, TBS, - nb_rb); - // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n", - // TBS, sdu_length_total, offset, TBS-sdu_length_total-offset); -#endif - - if (TBS - header_length_total - sdu_length_total - ta_len <= 2) { - padding = TBS - header_length_total - sdu_length_total - ta_len; - post_padding = 0; - } else { - padding = 0; - post_padding = 1; - } - - offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], - num_sdus, //num_sdus - sdu_lengths, // - sdu_lcids, - 255, // no drx - ta_update, // timing advance - NULL, // contention res id - padding, - post_padding); - - //#ifdef DEBUG_eNB_SCHEDULER - if (ta_update != 31) { - LOG_D(MAC, - "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_length %d\n", - module_idP, - frameP, - UE_id, - CC_id, - sdu_length_total, - num_sdus, - sdu_lengths[0], - sdu_lcids[0], - offset, - ta_update, - padding, - post_padding, - mcs, - TBS, - nb_rb, - header_length_total); - } - - //#endif -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n"); - - for (i = 0; i < 16; i++) { - LOG_T(MAC, "%x.", - dlsch_buffer[i]); - } - - LOG_T(MAC, "\n"); -#endif - // cycle through SDUs and place in dlsch_buffer - dlsch_pdu = &UE_list->DLSCH_pdu[CC_id][0][UE_id]; - memcpy(&dlsch_pdu->payload[0][offset], - dlsch_buffer, - sdu_length_total); - // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); - - // fill remainder of DLSCH with 0 - for (j = 0; j < (TBS - sdu_length_total - offset); j++) { - dlsch_pdu->payload[0][offset + sdu_length_total + j] = 0; - } - - trace_pdu(DIRECTION_DOWNLINK, - (uint8_t *) dlsch_pdu->payload[0], - TBS, - module_idP, - WS_C_RNTI, - UE_RNTI(module_idP, - UE_id), - eNB->frame, - eNB->subframe, - 0, - 0); - T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_BUFFER(dlsch_pdu->payload[0], - TBS)); - ue_template->nb_rb[harq_pid] = nb_rb; - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_SCHEDULED, - rnti); - // store stats - eNB->eNB_stats[CC_id].dlsch_bytes_tx += sdu_length_total; - eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1; - eNB_UE_stats->rbs_used = nb_rb; - eNB_UE_stats->num_mac_sdu_tx = num_sdus; - eNB_UE_stats->total_rbs_used += nb_rb; - eNB_UE_stats->dlsch_mcs2 = mcs; - eNB_UE_stats->TBS = TBS; - eNB_UE_stats->overhead_bytes = TBS - sdu_length_total; - eNB_UE_stats->total_sdu_bytes += sdu_length_total; - eNB_UE_stats->total_pdu_bytes += TBS; - eNB_UE_stats->total_num_pdus += 1; - - if (cc[CC_id].tdd_Config != NULL) { // TDD - ue_template->DAI++; - update_ul_dci(module_idP, - CC_id, - rnti, - ue_template->DAI, - subframeP); - } - - // do PUCCH power control - // this is the snr - // unit is not dBm, it's special from nfapi - // converting to dBm - snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10; - target_snr = eNB->puCch10xSnr / 10; - // this assumes accumulated tpc - // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out - int32_t framex10psubframe = ue_template->pucch_tpc_tx_frame * 10 + ue_template->pucch_tpc_tx_subframe; - - if (framex10psubframe + 10 <= (frameP * 10) + subframeP || //normal case - (framex10psubframe > (frameP * 10) + subframeP && 10240 - framex10psubframe + (frameP * 10) + subframeP >= 10)) //frame wrap-around - if (ue_sched_ctrl->pucch1_cqi_update[CC_id] == 1) { - ue_sched_ctrl->pucch1_cqi_update[CC_id] = 0; - ue_template->pucch_tpc_tx_frame = frameP; - ue_template->pucch_tpc_tx_subframe = subframeP; - - if (snr > target_snr + 4) { - tpc = 0; //-1 - } else if (snr < target_snr - 4) { - tpc = 2; //+1 - } else { - tpc = 1; //0 - } - - LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)\n", - module_idP, - frameP, - subframeP, - harq_pid, - tpc, - snr, - target_snr); - } // Po_PUCCH has been updated - else { - tpc = 1; //0 - } // time to do TPC update - else { - tpc = 1; //0 - } - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void *) dl_config_pdu, - 0, - sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dci_dl_pdu_idx]; + switch (get_tmode(module_idP, CC_id, UE_id)) { + case 1: + case 2: + case 7: + default: + LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", + rnti); dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = - get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI: see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1 - ue_template->oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; - //deactivate second codeword - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // Don't adjust power when retransmitting + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ue_template->oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = ue_template->oldmcs1[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round_DL & 3; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = rbc; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; - if (cc[CC_id].tdd_Config != NULL) { //TDD + // TDD + if (cc[CC_id].tdd_Config != NULL) { dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; - LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", + LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", module_idP, CC_id, harq_pid, - (ue_template->DAI - 1), - mcs); + round_DL, + ue_template->DAI - 1, + ue_template->oldmcs1[harq_pid]); } else { - LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", + LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", module_idP, CC_id, harq_pid, - mcs); + round_DL, + ue_template->oldmcs1[harq_pid]); } - LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n", - dl_req->number_pdu); + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; + eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dci_dl_pdu_idx + 1], + TBS, + -1, // retransmission, no pdu_index + rnti, + 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + rbc, // resource_block_coding + getQm(ue_template->oldmcs1[harq_pid]), + round_DL & 3, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0); // number of beamforming vectors, not used here + LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", + eNB->pdu_index[CC_id], + round_DL); + program_dlsch_acknak(module_idP, + CC_id, + UE_id, + frameP, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); + // No TX request for retransmission (check if null request for FAPI) + } - if (!CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - rnti)) { - ue_sched_ctrl->round[CC_id][harq_pid] = 0; - dl_req->number_dci++; - dl_req->number_pdu++; - dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; - eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP; - eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - /* CDRX */ - ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + //eNB_UE_stats->dlsch_trials[round]++; + eNB_UE_stats->num_retransmission += 1; + eNB_UE_stats->rbs_used_retx = nb_rb; + eNB_UE_stats->total_rbs_used_retx += nb_rb; + eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; + } else { + // Now check RLC information to compute number of required RBs + // get maximum TBS size for RLC request + const int nb_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; + int TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rb); + const uint32_t rbc = allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); - if (ue_sched_ctrl->cdrx_configured) { - ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission - ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission - /* - * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. - */ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer); + // add the length for all the control elements (timing adv, drx, etc) : header + payload - if (harq_pid == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); - } - } + if (ue_sched_ctrl->ta_timer) + ue_sched_ctrl->ta_timer--; - // Toggle NDI for next time - LOG_D(MAC, "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", - CC_id, - frameP, - subframeP, - UE_id, - rnti, - harq_pid, - ue_template->oldNDI[harq_pid]); - ue_template->oldNDI[harq_pid] = 1 - ue_template->oldNDI[harq_pid]; - ue_template->oldmcs1[harq_pid] = mcs; - ue_template->oldmcs2[harq_pid] = 0; - AssertFatal(ue_template->physicalConfigDedicated != NULL, "physicalConfigDedicated is NULL\n"); - AssertFatal(ue_template->physicalConfigDedicated->pdsch_ConfigDedicated != NULL, - "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); - fill_nfapi_dlsch_config(eNB, - dl_req, - TBS, - eNB->pdu_index[CC_id], - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later - getQm(mcs), - 0, // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0); // number of beamforming vectors, not used here - eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, - (frameP * 10) + subframeP, - TBS, - eNB->pdu_index[CC_id], - dlsch_pdu->payload[0]); - LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n", - eNB->pdu_index[CC_id]); - eNB->pdu_index[CC_id]++; - program_dlsch_acknak(module_idP, - CC_id, - UE_id, - frameP, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - } else { - LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n", - frameP, - subframeP, - UE_id, - rnti); - } - } else { // There is no data from RLC or MAC header, so don't schedule + int ta_update = 31; + if (ue_sched_ctrl->ta_timer == 0) { + ta_update = ue_sched_ctrl->ta_update; + + /* if we send TA then set timer to not send it for a while */ + if (ta_update != 31) { + ue_sched_ctrl->ta_timer = 20; + } + + /* reset ta_update */ + ue_sched_ctrl->ta_update = 31; + } + + int ta_len = (ta_update != 31) ? 2 : 0; + + + int num_sdus = 0; + uint16_t sdu_lengths[NB_RB_MAX]; + int sdu_length_total = 0; + int header_length_total = 0; + int header_length_last = 0; + unsigned char sdu_lcids[NB_RB_MAX]; + for (int i = 0; i < ue_sched_ctrl->dl_lc_num; ++i) { + const int lcid = ue_sched_ctrl->dl_lc_ids[i]; // will match DCCH, DCCH1, DTCH + + if (TBS - ta_len - header_length_total - sdu_length_total - 3 <= 0) + break; + + if (ue_sched_ctrl->dl_lc_bytes[i] == 0) // no data in this LC! + continue; + + LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, LC%d->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", + module_idP, + frameP, + subframeP, + lcid, + CC_id, + TBS - ta_len - header_length_total - sdu_length_total - 3); + + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS - ta_len - header_length_total - sdu_length_total - 3, + (char *)&dlsch_buffer[sdu_length_total], + 0, + 0 + ); + +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC, "[eNB %d][%d] CC_id %d Got %d bytes :", + module_idP, + lcid, + CC_id, + sdu_lengths[num_sdus]); + for (int j = 0; j < sdu_lengths[num_sdus]; ++j) + LOG_T(MAC, "%x ", dlsch_buffer[sdu_length_total + j]); + LOG_T(MAC, "\n"); +#endif + + T(T_ENB_MAC_UE_DL_SDU, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(lcid), + T_INT(sdu_lengths[num_sdus])); + LOG_D(MAC, "[eNB %d][LC %d] CC_id %d Got %d bytes from RLC\n", + module_idP, + lcid, + CC_id, + sdu_lengths[num_sdus]); + sdu_lcids[num_sdus] = lcid; + sdu_length_total += sdu_lengths[num_sdus]; + eNB_UE_stats->num_pdu_tx[lcid] += 1; + eNB_UE_stats->lcid_sdu[num_sdus] = lcid; + eNB_UE_stats->sdu_length_tx[lcid] = sdu_lengths[num_sdus]; + eNB_UE_stats->num_bytes_tx[lcid] += sdu_lengths[num_sdus]; + header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); + header_length_total += header_length_last; + num_sdus += 1; + + if (lcid >= 3) { // if this is DTCH + ue_sched_ctrl->uplane_inactivity_timer = 0; + + // reset RRC inactivity timer after uplane activity + rrc_eNB_ue_context_t *ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti); + if (ue_contextP == NULL) + LOG_E(MAC, "[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer\n", + module_idP, + CC_id, + rnti); + ue_contextP->ue_context.ue_rrc_inactivity_timer = 1; } } - if (cc[CC_id].tdd_Config != NULL) { // TDD - set_ul_DAI(module_idP, - UE_id, - CC_id, - frameP, - subframeP); + /* Last header does not have length field */ + if (header_length_total) { + header_length_total -= header_length_last; + header_length_total++; } - } // UE_id loop - } // CC_id loop - fill_DLSCH_dci(module_idP, - frameP, - subframeP, - mbsfn_flag); + // there is at least one SDU or TA command + if (ta_len + sdu_length_total + header_length_total > 0) { + // Now compute number of required RBs for total sdu length + // Assume RAH format 2 + int mcs = eNB_UE_stats->dlsch_mcs1; + + /* TODO make special function */ + // decrease mcs until TBS falls below required length + while ((TBS > sdu_length_total + header_length_total + ta_len) && (mcs > 0)) { + mcs--; + TBS = get_TBS_DL(mcs, nb_rb); + } + + // if we have decreased too much or we don't have enough RBs, increase MCS + while (TBS < sdu_length_total + header_length_total + ta_len && mcs < 28) { + // the second part of this condition is useless since dl_pow_off is + // always 2? + //&& ((ue_sched_ctrl->dl_pow_off[CC_id] > 0 && mcs < 28) || (ue_sched_ctrl->dl_pow_off[CC_id] == 0 && mcs <= 15))) { + mcs++; + TBS = get_TBS_DL(mcs, + nb_rb); + } + + LOG_D(MAC, "dlsch_mcs before and after the rate matching = (%d, %d), TBS %d, nb_rb %d\n", + eNB_UE_stats->dlsch_mcs1, mcs, TBS, nb_rb); + + int post_padding = TBS - header_length_total - sdu_length_total - ta_len > 2; + int padding = post_padding ? 0 : TBS - header_length_total - sdu_length_total - ta_len; + + const int offset = generate_dlsch_header((unsigned char *) UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], + num_sdus, //num_sdus + sdu_lengths, // + sdu_lcids, + 255, // no drx + ta_update, // timing advance + NULL, // contention res id + padding, + post_padding); + + //#ifdef DEBUG_eNB_SCHEDULER + if (ta_update != 31) { + LOG_D(MAC, + "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_length %d\n", + module_idP, + frameP, + UE_id, + CC_id, + sdu_length_total, + num_sdus, + sdu_lengths[0], + sdu_lcids[0], + offset, + ta_update, + padding, + post_padding, + mcs, + TBS, + nb_rb, + header_length_total); + } + + //#endif +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n"); + + for (int i = 0; i < 16; i++) { + LOG_T(MAC, "%x.", + dlsch_buffer[i]); + } + + LOG_T(MAC, "\n"); +#endif + // cycle through SDUs and place in dlsch_buffer + DLSCH_PDU *dlsch_pdu = &UE_info->DLSCH_pdu[CC_id][0][UE_id]; + memcpy(&dlsch_pdu->payload[0][offset], dlsch_buffer, sdu_length_total); + + // fill remainder of DLSCH with 0 + for (int j = 0; j < TBS - sdu_length_total - offset; j++) { + dlsch_pdu->payload[0][offset + sdu_length_total + j] = 0; + } + + trace_pdu(DIRECTION_DOWNLINK, + (uint8_t *) dlsch_pdu->payload[0], + TBS, + module_idP, + WS_C_RNTI, + UE_RNTI(module_idP, + UE_id), + eNB->frame, + eNB->subframe, + 0, + 0); + T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_BUFFER(dlsch_pdu->payload[0], + TBS)); + ue_template->nb_rb[harq_pid] = nb_rb; + // store stats + eNB->eNB_stats[CC_id].dlsch_bytes_tx += sdu_length_total; + eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1; + eNB_UE_stats->rbs_used = nb_rb; + eNB_UE_stats->num_mac_sdu_tx = num_sdus; + eNB_UE_stats->total_rbs_used += nb_rb; + eNB_UE_stats->dlsch_mcs2 = mcs; + eNB_UE_stats->TBS = TBS; + eNB_UE_stats->overhead_bytes = TBS - sdu_length_total; + eNB_UE_stats->total_sdu_bytes += sdu_length_total; + eNB_UE_stats->total_pdu_bytes += TBS; + eNB_UE_stats->total_num_pdus += 1; + + if (cc[CC_id].tdd_Config != NULL) { // TDD + ue_template->DAI++; + update_ul_dci(module_idP, + CC_id, + rnti, + ue_template->DAI, + subframeP); + } + + // do PUCCH power control + // this is the snr + // unit is not dBm, it's special from nfapi + // converting to dBm + int snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10; + int target_snr = eNB->puCch10xSnr / 10; + // this assumes accumulated tpc + // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out + int32_t framex10psubframe = ue_template->pucch_tpc_tx_frame * 10 + ue_template->pucch_tpc_tx_subframe; + + int tpc = 1; + if (framex10psubframe + 10 <= (frameP * 10) + subframeP || //normal case + (framex10psubframe > (frameP * 10) + subframeP && 10240 - framex10psubframe + (frameP * 10) + subframeP >= 10)) { //frame wrap-around + if (ue_sched_ctrl->pucch1_cqi_update[CC_id] == 1) { + ue_sched_ctrl->pucch1_cqi_update[CC_id] = 0; + ue_template->pucch_tpc_tx_frame = frameP; + ue_template->pucch_tpc_tx_subframe = subframeP; + + if (snr > target_snr + 4) { + tpc = 0; //-1 + } else if (snr < target_snr - 4) { + tpc = 2; //+1 + } else { + tpc = 1; //0 + } + + LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)\n", + module_idP, + frameP, + subframeP, + harq_pid, + tpc, + snr, + target_snr); + } // Po_PUCCH has been updated + } + + nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dci_dl_pdu_idx]; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1 - ue_template->oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; + //deactivate second codeword + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = rbc; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; + + if (cc[CC_id].tdd_Config != NULL) { //TDD + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; + LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + (ue_template->DAI - 1), + mcs); + } else { + LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + mcs); + } + + LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n", + dl_req->number_pdu); + + ue_sched_ctrl->round[CC_id][harq_pid] = 0; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP; + eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; + /* CDRX */ + ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + + if (ue_sched_ctrl->cdrx_configured) { + ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission + ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + /* + * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. + */ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer); + + if (harq_pid == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); + } + } + + // Toggle NDI for next time + LOG_D(MAC, "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", + CC_id, + frameP, + subframeP, + UE_id, + rnti, + harq_pid, + ue_template->oldNDI[harq_pid]); + ue_template->oldNDI[harq_pid] = 1 - ue_template->oldNDI[harq_pid]; + ue_template->oldmcs1[harq_pid] = mcs; + ue_template->oldmcs2[harq_pid] = 0; + AssertFatal(ue_template->physicalConfigDedicated != NULL, "physicalConfigDedicated is NULL\n"); + AssertFatal(ue_template->physicalConfigDedicated->pdsch_ConfigDedicated != NULL, + "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dci_dl_pdu_idx + 1], + TBS, + eNB->pdu_index[CC_id], + rnti, + 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + rbc,// resource_block_coding + getQm(mcs), + 0, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0); // number of beamforming vectors, not used here + eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, + (frameP * 10) + subframeP, + TBS, + eNB->pdu_index[CC_id], + dlsch_pdu->payload[0]); + LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n", + eNB->pdu_index[CC_id]); + eNB->pdu_index[CC_id]++; + program_dlsch_acknak(module_idP, + CC_id, + UE_id, + frameP, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); + } + } + } // UE_id loop stop_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_OUT); } -//------------------------------------------------------------------------------ -void -dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, - int frameP, - sub_frame_t subframeP, - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) -//------------------------------------------------------------------------------ -{ - // FIXME: I'm prototyping the algorithm, so there may be arrays and variables that carry redundant information here and in pre_processor_results struct. - int UE_id, CC_id, rbg, i; - int N_RB_DL, min_rb_unit, tm; - int owned, used; - eNB_MAC_INST *eNB = RC.mac[Mod_id]; - int nb_mac_CC = RC.nb_mac_CC[Mod_id]; - UE_list_t *UE_list = &eNB->UE_list; - slice_info_t *sli = &eNB->slice_info; - UE_sched_ctrl_t *ue_sched_ctl; - COMMON_channels_t *cc; - int N_RBG[NFAPI_CC_MAX]; - int slice_sorted_list[MAX_NUM_SLICES]; - int slice_idx; - int8_t free_rbgs_map[NFAPI_CC_MAX][N_RBG_MAX]; - int has_traffic[NFAPI_CC_MAX][MAX_NUM_SLICES]; - uint8_t allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]; - uint16_t (*nb_rbs_remaining)[MAX_MOBILES_PER_ENB]; - uint16_t (*nb_rbs_required)[MAX_MOBILES_PER_ENB]; - uint8_t (*MIMO_mode_indicator)[N_RBG_MAX]; - - // Initialize the free RBGs map - // free_rbgs_map[CC_id][rbg] = -1 if RBG is allocated, - // otherwise it contains the id of the slice it belongs to. - // (Information about slicing must be retained to deal with isolation). - // FIXME: This method does not consider RBGs that are free and belong to no slices - for (CC_id = 0; CC_id < nb_mac_CC; CC_id++) { - cc = &eNB->common_channels[CC_id]; - N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); - - for (rbg = 0; rbg < N_RBG[CC_id]; rbg++) { - for (i = 0; i < sli->n_dl; ++i) { - owned = sli->pre_processor_results[i].slice_allocation_mask[CC_id][rbg]; - - if (owned) { - used = rballoc_sub[CC_id][rbg]; - free_rbgs_map[CC_id][rbg] = used ? -1 : i; - break; - } - } - } - } - - // Find out which slices need other resources. - // FIXME: I don't think is really needed since we check nb_rbs_remaining later - for (CC_id = 0; CC_id < nb_mac_CC; CC_id++) { - for (i = 0; i < sli->n_dl; i++) { - has_traffic[CC_id][i] = 0; - - for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (sli->pre_processor_results[i].nb_rbs_remaining[CC_id][UE_id] > 0) { - has_traffic[CC_id][i] = 1; - break; - } - } - } - } - - slice_priority_sort(Mod_id, - slice_sorted_list); - - // MULTIPLEXING - // This part is an adaptation of dlsch_scheduler_pre_processor_allocate() code - for (CC_id = 0; CC_id < nb_mac_CC; ++CC_id) { - N_RB_DL = to_prb(eNB->common_channels[CC_id].mib->message.dl_Bandwidth); - min_rb_unit = get_min_rb_unit(Mod_id, - CC_id); - - for (i = 0; i < sli->n_dl; ++i) { - slice_idx = slice_sorted_list[i]; - - if (has_traffic[CC_id][slice_idx] == 0) continue; - - // Build an ad-hoc allocation mask fo the slice - for (rbg = 0; rbg < N_RBG[CC_id]; ++rbg) { - if (free_rbgs_map[CC_id][rbg] == -1) { - // RBG is already allocated - allocation_mask[CC_id][rbg] = 0; - continue; - } - - if (sli->dl[free_rbgs_map[CC_id][rbg]].isol == 1) { - // RBG belongs to an isolated slice - allocation_mask[CC_id][rbg] = 0; - continue; - } - - // RBG is free - allocation_mask[CC_id][rbg] = 1; - } - - // Sort UE again - // (UE list gets sorted every time pre_processor is called so it is probably dirty at this point) - // FIXME: There is only one UE_list for all slices, so it must be sorted again each time we use it - sort_UEs(Mod_id, - slice_idx, - frameP, - subframeP); - nb_rbs_remaining = sli->pre_processor_results[slice_idx].nb_rbs_remaining; - nb_rbs_required = sli->pre_processor_results[slice_idx].nb_rbs_required; - MIMO_mode_indicator = sli->pre_processor_results[slice_idx].MIMO_mode_indicator; - - // Allocation - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - tm = get_tmode(Mod_id, - CC_id, - UE_id); - - for (rbg = 0; rbg < N_RBG[CC_id]; ++rbg) { - // FIXME: I think that some of these checks are redundant - if (allocation_mask[CC_id][rbg] == 0) continue; - - if (rballoc_sub[CC_id][rbg] != 0) continue; - - if (ue_sched_ctl->rballoc_sub_UE[CC_id][rbg] != 0) continue; - - if (nb_rbs_remaining[CC_id][UE_id] <= 0) continue; - - if (ue_sched_ctl->pre_nb_available_rbs[CC_id] >= nb_rbs_required[CC_id][UE_id]) continue; - - if (ue_sched_ctl->dl_pow_off[CC_id] == 0) continue; - - if ((rbg == N_RBG[CC_id] - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { - // Allocating last, smaller RBG - if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) { - rballoc_sub[CC_id][rbg] = 1; - free_rbgs_map[CC_id][rbg] = -1; - ue_sched_ctl->rballoc_sub_UE[CC_id][rbg] = 1; - MIMO_mode_indicator[CC_id][rbg] = 1; - - if (tm == 5) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - - nb_rbs_remaining[CC_id][UE_id] -= (min_rb_unit - 1); - ue_sched_ctl->pre_nb_available_rbs[CC_id] += (min_rb_unit - 1); - } - } else { - // Allocating a standard-sized RBG - if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) { - rballoc_sub[CC_id][rbg] = 1; - free_rbgs_map[CC_id][rbg] = -1; - ue_sched_ctl->rballoc_sub_UE[CC_id][rbg] = 1; - MIMO_mode_indicator[CC_id][rbg] = 1; - - if (tm == 5) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - - nb_rbs_remaining[CC_id][UE_id] -= min_rb_unit; - ue_sched_ctl->pre_nb_available_rbs[CC_id] += min_rb_unit; - } - } - } - } - } - } - - return; -} - -//------------------------------------------------------------------------------ -void dlsch_scheduler_qos_multiplexing(module_id_t Mod_id, int frameP, sub_frame_t subframeP) -//------------------------------------------------------------------------------ -{ - // int UE_id; - int CC_id, i; - // UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - slice_info_t *sli = &RC.mac[Mod_id]->slice_info; - //UE_sched_ctrl *ue_sched_ctl; - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - for (i = 0; i < sli->n_dl; i++) { - // Sort UE again - // FIXME: There is only one UE_list for all slices, so it must be sorted again each time we use it - sort_UEs(Mod_id, - (uint8_t)i, - frameP, - subframeP); - /* - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - //ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - // TODO: Do something here - // ue_sched_ctl->pre_nb_available_rbs[CC_id]; - } - */ - } - } -} - //------------------------------------------------------------------------------ /* * Default DLSCH scheduler for LTE-M @@ -1886,7 +1234,7 @@ schedule_ue_spec_br(module_id_t module_idP, unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; eNB_MAC_INST *mac = RC.mac[module_idP]; COMMON_channels_t *cc = mac->common_channels; - UE_list_t *UE_list = &mac->UE_list; + UE_info_t *UE_info = &mac->UE_info; UE_TEMPLATE *UE_template = NULL; UE_sched_ctrl_t *ue_sched_ctl = NULL; nfapi_dl_config_request_pdu_t *dl_config_pdu = NULL; @@ -1951,7 +1299,7 @@ schedule_ue_spec_br(module_id_t module_idP, } } - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { int harq_pid = 0; rnti = UE_RNTI(module_idP, UE_id); @@ -1959,8 +1307,8 @@ schedule_ue_spec_br(module_id_t module_idP, continue; } - ue_sched_ctl = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template = &(UE_list->UE_template[CC_id][UE_id]); + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; if (UE_template->rach_resource_type == 0) { continue; @@ -2031,7 +1379,6 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, - (TBS-ta_len-header_len_dcch), 0, 0); // transport block set size sdu_lengths[0] = 0; @@ -2049,7 +1396,7 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, - TBS, //not used + TBS-ta_len-header_len_dcch, (char *)&dlsch_buffer[0], 0, 0); @@ -2068,8 +1415,8 @@ schedule_ue_spec_br(module_id_t module_idP, sdu_lengths[0]); sdu_length_total = sdu_lengths[0]; sdu_lcids[0] = DCCH; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH]+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH]+=sdu_lengths[0]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH]+=1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH]+=sdu_lengths[0]; num_sdus = 1; } else { header_len_dcch = 0; @@ -2087,7 +1434,6 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, - (TBS-ta_len-header_len_dcch-sdu_length_total), 0, 0); // transport block set size less allocations for timing advance and DCCH SDU sdu_lengths[num_sdus] = 0; @@ -2105,7 +1451,7 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH+1, - TBS, //not used + TBS-ta_len-header_len_dcch-sdu_length_total, (char *)&dlsch_buffer[sdu_length_total], 0, 0); @@ -2121,8 +1467,8 @@ schedule_ue_spec_br(module_id_t module_idP, sdu_lcids[num_sdus] = DCCH1; sdu_length_total += sdu_lengths[num_sdus]; header_len_dcch += 2; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1] += 1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1] += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; num_sdus++; } } @@ -2152,7 +1498,6 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS - ta_len - header_len_dcch - sdu_length_total - header_len_dtch, 0, 0); @@ -2183,7 +1528,7 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS, //not used + TBS - ta_len - header_len_dcch - sdu_length_total - header_len_dtch, (char *) &dlsch_buffer[sdu_length_total], 0, 0); @@ -2274,7 +1619,7 @@ schedule_ue_spec_br(module_id_t module_idP, post_padding = TBS - sdu_length_total - header_len_dcch - header_len_dtch - ta_len; // 1 is for the postpadding header } - offset = generate_dlsch_header((unsigned char *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + offset = generate_dlsch_header((unsigned char *)UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus sdu_lengths, // sdu_lcids, @@ -2307,15 +1652,15 @@ schedule_ue_spec_br(module_id_t module_idP, } /* Cycle through SDUs and place in dlsch_buffer */ - memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset], dlsch_buffer, sdu_length_total); + memcpy(&UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset], dlsch_buffer, sdu_length_total); /* Fill remainder of DLSCH with random data */ for (j = 0; j < (TBS - sdu_length_total - offset); j++) { - UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset + sdu_length_total + j] = (char)(taus()&0xff); + UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset + sdu_length_total + j] = (char)(taus()&0xff); } trace_pdu(DIRECTION_DOWNLINK, - (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + (uint8_t *)UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS, module_idP, 3, @@ -2331,7 +1676,7 @@ schedule_ue_spec_br(module_id_t module_idP, T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), - T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS)); + T_BUFFER(UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS)); /* Do PUCCH power control */ /* This is the snr */ /* unit is not dBm, it's special from nfapi, convert to dBm */ @@ -2339,15 +1684,15 @@ schedule_ue_spec_br(module_id_t module_idP, target_snr = mac->puCch10xSnr / 10; /* This assumes accumulated tpc */ /* Make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out */ - int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame * 10 + UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; + int32_t framex10psubframe = UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame * 10 + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; if (((framex10psubframe + 10) <= (frameP * 10 + subframeP)) || // normal case ((framex10psubframe > (frameP * 10 + subframeP)) && (((10240 - framex10psubframe +frameP * 10 + subframeP) >= 10)))) { // frame wrap-around if (ue_sched_ctl->pucch1_cqi_update[CC_id] == 1) { ue_sched_ctl->pucch1_cqi_update[CC_id] = 0; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frameP; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframeP; + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frameP; + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframeP; if (snr > target_snr + 4) { tpc = 0; //-1 @@ -2481,7 +1826,7 @@ schedule_ue_spec_br(module_id_t module_idP, TX_req->pdu_index = mac->pdu_index[CC_id]++; TX_req->num_segments = 1; TX_req->segments[0].segment_length = TX_req->pdu_length; - TX_req->segments[0].segment_data = mac->UE_list.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0]; + TX_req->segments[0].segment_data = mac->UE_info.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0]; mac->TX_req[CC_id].tx_request_body.number_of_pdus++; ackNAK_absSF = absSF + 4; ul_req = &mac->UL_req_tmp[CC_id][ackNAK_absSF % 10].ul_config_request_body; @@ -2515,9 +1860,9 @@ schedule_ue_spec_br(module_id_t module_idP, T_INT (frameP), T_INT (subframeP), T_INT (0 /* harq_pid always 0? */ ), - T_BUFFER (&mac->UE_list.DLSCH_pdu[CC_id][0][UE_id].payload[0], TX_req->pdu_length)); + T_BUFFER (&mac->UE_info.DLSCH_pdu[CC_id][0][UE_id].payload[0], TX_req->pdu_length)); trace_pdu(1, - (uint8_t *) mac->UE_list.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0], + (uint8_t *) mac->UE_info.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0], TX_req->pdu_length, UE_id, 3, @@ -2530,101 +1875,6 @@ schedule_ue_spec_br(module_id_t module_idP, } // end loop on UE_id } -//------------------------------------------------------------------------------ -void -fill_DLSCH_dci(module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP, - int *mbsfn_flagP) -//------------------------------------------------------------------------------ -{ - // loop over all allocated UEs and compute frequency allocations for PDSCH - int UE_id = -1; - uint8_t /* first_rb, */ nb_rb = 3; - rnti_t rnti; - //unsigned char *vrb_map; - uint8_t rballoc_sub[25]; - //uint8_t number_of_subbands=13; - //unsigned char round; - unsigned char harq_pid; - int i; - int CC_id; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - int N_RBG; - int N_RB_DL; - COMMON_channels_t *cc; - eNB_DLSCH_INFO *dlsch_info; - UE_TEMPLATE *ue_template; - start_meas(&eNB->fill_DLSCH_dci); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, - VCD_FUNCTION_IN); - - for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - LOG_D(MAC, "Doing fill DCI for CC_id %d\n", - CC_id); - - if (mbsfn_flagP[CC_id] > 0) - continue; - - cc = &eNB->common_channels[CC_id]; - N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); - N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); - - // UE specific DCIs - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - dlsch_info = &eNB_dlsch_info[module_idP][CC_id][UE_id]; - LOG_T(MAC, "CC_id %d, UE_id: %d => status %d\n", - CC_id, - UE_id, - dlsch_info->status); - - if (dlsch_info->status == S_DL_SCHEDULED) { - // clear scheduling flag - dlsch_info->status = S_DL_WAITING; - rnti = UE_RNTI(module_idP, UE_id); - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP, - subframeP); - ue_template = &UE_list->UE_template[CC_id][UE_id]; - nb_rb = ue_template->nb_rb[harq_pid]; - - /// Synchronizing rballoc with rballoc_sub - for (i = 0; i < N_RBG; i++) { - rballoc_sub[i] = ue_template->rballoc_subband[harq_pid][i]; - } - - nfapi_dl_config_request_body_t *dl_config_request_body = &RC.mac[module_idP]->DL_req[CC_id].dl_config_request_body; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - - for (i = 0; i < dl_config_request_body->number_pdu; i++) { - dl_config_pdu = &dl_config_request_body->dl_config_pdu_list[i]; - - if (dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE && - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti == rnti && - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format != 1) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = allocate_prbs_sub(nb_rb, - N_RB_DL, - N_RBG, - rballoc_sub); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; - } else if (dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE && - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == rnti && - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type == 0) { - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = allocate_prbs_sub(nb_rb, - N_RB_DL, - N_RBG, - rballoc_sub); - } - } - } - } - } - - stop_meas(&eNB->fill_DLSCH_dci); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, - VCD_FUNCTION_OUT); -} - //------------------------------------------------------------------------------ unsigned char *get_dlsch_sdu(module_id_t module_idP, int CC_id, @@ -2661,7 +1911,7 @@ unsigned char *get_dlsch_sdu(module_id_t module_idP, CC_id, rntiP, UE_id); - return ((unsigned char *) &eNB->UE_list.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]); + return ((unsigned char *) &eNB->UE_info.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]); } LOG_E(MAC, "[eNB %d] Frame %d: CC_id %d UE with RNTI %x does not exist\n", @@ -2706,61 +1956,61 @@ set_ue_dai(sub_frame_t subframeP, int UE_id, uint8_t CC_id, uint8_t tdd_config, - UE_list_t *UE_list) + UE_info_t *UE_info) //------------------------------------------------------------------------------ { switch (tdd_config) { case 0: if (subframeP == 0 || subframeP == 1 || subframeP == 3 || subframeP == 5 || subframeP == 6 || subframeP == 8) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 1: if (subframeP == 0 || subframeP == 4 || subframeP == 5 || subframeP == 9) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 2: if (subframeP == 4 || subframeP == 5) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 3: if (subframeP == 5 || subframeP == 7 || subframeP == 9) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 4: if (subframeP == 0 || subframeP == 6) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 5: if (subframeP == 9) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 6: if (subframeP == 0 || subframeP == 1 || subframeP == 5 || subframeP == 6 || subframeP == 9) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; default: - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; LOG_I(MAC, "unknown TDD config %d\n", tdd_config); break; @@ -3158,37 +2408,3 @@ schedule_PCH(module_id_t module_idP, stop_meas(&eNB->schedule_pch); return; } - -static int -slice_priority_compare(const void *_a, - const void *_b, - void *_c) { - const int slice_id1 = *(const int *) _a; - const int slice_id2 = *(const int *) _b; - const module_id_t Mod_id = *(int *) _c; - const slice_info_t *sli = &RC.mac[Mod_id]->slice_info; - - if (sli->dl[slice_id1].prio > sli->dl[slice_id2].prio) { - return -1; - } - - return 1; -} - -void -slice_priority_sort(module_id_t Mod_id, - int slice_list[MAX_NUM_SLICES]) { - int i; - int n_dl = RC.mac[Mod_id]->slice_info.n_dl; - - for (i = 0; i < n_dl; i++) { - slice_list[i] = i; - } - - qsort_r(slice_list, - n_dl, - sizeof(int), - slice_priority_compare, - &Mod_id); - return; -} diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 260d8a7417..00fd40109d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -120,7 +120,7 @@ void pre_scd_nb_rbs_required( module_id_t module_idP, if(N_RB_DL==100) step_size=4; memset(nb_rbs_required, 0, sizeof(uint16_t)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; for (UE_id = 0; UE_id dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; if (UE_template.dl_buffer_total > 0) { nb_rbs_required[CC_id][UE_id] = search_rbs_required(eNB_UE_stats->dlsch_mcs1, UE_template.dl_buffer_total, N_RB_DL, step_size); @@ -175,7 +175,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]) { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; UE_sched_ctrl_t *ue_sched_ctl; uint8_t CC_id; int UE_id; @@ -208,7 +208,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( DL_req = &eNB->DL_req[CC_id].dl_config_request_body; for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - if (UE_list->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == FALSE) { continue; } @@ -222,12 +222,12 @@ void dlsch_scheduler_pre_ue_select_fairRR( continue; } - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = frame_subframe2_dl_harq_pid(cc[CC_id].tdd_Config,frameP,subframeP); round = ue_sched_ctl->round[CC_id][harq_pid]; if (round != 8) { // retransmission - if(UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] == 0) { + if(UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid] == 0) { continue; } @@ -266,7 +266,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (format_flag == 0)?2:1; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation; DL_req->number_pdu++; - nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + nb_rbs_required[CC_id][UE_id] = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; // Insert DLSCH(retransmission) UE into selected UE list dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].UE_id = UE_id; dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].ue_priority = SCH_DL_RETRANS; @@ -284,7 +284,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( UE_id, CC_id, cc[CC_id].tdd_Config->subframeAssignment, - UE_list); + UE_info); // update UL DAI after DLSCH scheduling set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); } @@ -324,7 +324,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( break; } - if (UE_list->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == FALSE) { continue; } @@ -337,7 +337,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( continue; } - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; for(i = 0; isubframeAssignment, - UE_list); + UE_info); // update UL DAI after DLSCH scheduling set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); } @@ -448,7 +448,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( break; } - if (UE_list->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == FALSE) { continue; } @@ -461,7 +461,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( continue; } - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; for(i = 0; isubframeAssignment, - UE_list); + UE_info); // update UL DAI after DLSCH scheduling set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); } @@ -558,7 +558,331 @@ void dlsch_scheduler_pre_ue_select_fairRR( return; } +void dlsch_scheduler_pre_processor_reset_fairRR( + module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + int min_rb_unit[NFAPI_CC_MAX], + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], + uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { + int UE_id; + uint8_t CC_id; + int i, j; + UE_info_t *UE_info; + UE_sched_ctrl_t *ue_sched_ctl; + int N_RB_DL, RBGsize, RBGsize_last; + int N_RBG[NFAPI_CC_MAX]; + rnti_t rnti; + uint8_t *vrb_map; + COMMON_channels_t *cc; + // + for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { + // initialize harq_pid and round + cc = &RC.mac[module_idP]->common_channels[CC_id]; + N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); + min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); + + for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) { + UE_info = &RC.mac[module_idP]->UE_info; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; + rnti = UE_RNTI(module_idP, UE_id); + + if (rnti == NOT_A_RNTI) + continue; + + if (UE_info->active[UE_id] != TRUE) + continue; + + LOG_D(MAC, "Running preprocessor for UE %d (%x)\n", UE_id, rnti); + + // initialize harq_pid and round + if (ue_sched_ctl->ta_timer) + ue_sched_ctl->ta_timer--; + + /* + eNB_UE_stats *eNB_UE_stats; + + if (eNB_UE_stats == NULL) + return; + + + mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti, + frameP,subframeP, + &ue_sched_ctl->harq_pid[CC_id], + &ue_sched_ctl->round[CC_id], + openair_harq_DL); + + + if (ue_sched_ctl->ta_timer == 0) { + + // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ... + + ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY + switch (N_RB_DL) { + case 6: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update; + break; + + case 15: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2; + break; + + case 25: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4; + break; + + case 50: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8; + break; + + case 75: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12; + break; + + case 100: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16; + break; + } + // clear the update in case PHY does not have a new measurement after timer expiry + eNB_UE_stats->timing_advance_update = 0; + } + else { + ue_sched_ctl->ta_timer--; + ue_sched_ctl->ta_update =0; // don't trigger a timing advance command + } + + + if (UE_id==0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update); + } + */ + nb_rbs_required[CC_id][UE_id] = 0; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; + ue_sched_ctl->dl_pow_off[CC_id] = 2; + + for (i = 0; i < N_RBG[CC_id]; i++) { + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; + } + } + + N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); + + switch (N_RB_DL) { + case 6: + RBGsize = 1; + RBGsize_last = 1; + break; + + case 15: + RBGsize = 2; + RBGsize_last = 1; + break; + + case 25: + RBGsize = 2; + RBGsize_last = 1; + break; + + case 50: + RBGsize = 3; + RBGsize_last = 2; + break; + + case 75: + RBGsize = 4; + RBGsize_last = 3; + break; + + case 100: + RBGsize = 4; + RBGsize_last = 4; + break; + + default: + AssertFatal(1 == 0, "unsupported RBs (%d)\n", N_RB_DL); + } + + vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map; + + // Initialize Subbands according to VRB map + for (i = 0; i < N_RBG[CC_id]; i++) { + int rb_size = i == N_RBG[CC_id] - 1 ? RBGsize_last : RBGsize; + + // for SI-RNTI,RA-RNTI and P-RNTI allocations + for (j = 0; j < rb_size; j++) { + if (vrb_map[j + (i*RBGsize)] != 0) { + rballoc_sub[CC_id][i] = 1; + LOG_D(MAC, "Frame %d, subframe %d : vrb %d allocated\n", frameP, subframeP, j + (i*RBGsize)); + break; + } + } + + //LOG_D(MAC, "Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n", + //frameP, subframeP, CC_id, i, rballoc_sub[CC_id][i]); + MIMO_mode_indicator[CC_id][i] = 2; + } + } +} + +// This function returns the estimated number of RBs required by each UE for downlink scheduling +void assign_rbs_required_fairRR( + module_id_t Mod_id, + frame_t frameP, + sub_frame_t subframe, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) { + uint16_t TBS = 0; + int UE_id, n, i, j, CC_id, pCCid, tmp; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j; + int N_RB_DL; + + // clear rb allocations across all CC_id + for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { + if (UE_info->active[UE_id] != TRUE) + continue; + + pCCid = UE_PCCID(Mod_id, UE_id); + + // update CQI information across component carriers + for (n = 0; n < UE_info->numactiveCCs[UE_id]; n++) { + CC_id = UE_info->ordered_CCids[n][UE_id]; + eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; + eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + } + + // provide the list of CCs sorted according to MCS + for (i = 0; i < UE_info->numactiveCCs[UE_id]; ++i) { + eNB_UE_stats_i = + &UE_info->eNB_UE_stats[UE_info->ordered_CCids[i][UE_id]][UE_id]; + + for (j = i + 1; j < UE_info->numactiveCCs[UE_id]; j++) { + DevAssert(j < NFAPI_CC_MAX); + eNB_UE_stats_j = + &UE_info->eNB_UE_stats[UE_info->ordered_CCids[j][UE_id]][UE_id]; + + if (eNB_UE_stats_j->dlsch_mcs1 > eNB_UE_stats_i->dlsch_mcs1) { + tmp = UE_info->ordered_CCids[i][UE_id]; + UE_info->ordered_CCids[i][UE_id] = UE_info->ordered_CCids[j][UE_id]; + UE_info->ordered_CCids[j][UE_id] = tmp; + } + } + } + + if (UE_info->UE_template[pCCid][UE_id].dl_buffer_total > 0) { + LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id); + + for (i = 0; i < UE_info->numactiveCCs[UE_id]; i++) { + CC_id = UE_info->ordered_CCids[i][UE_id]; + eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; + const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); + + if (eNB_UE_stats->dlsch_mcs1 == 0) { + nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small + } else { + nb_rbs_required[CC_id][UE_id] = min_rb_unit; + } + + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]); + LOG_D(MAC, + "[preprocessor] start RB assignement for UE %d CC_id %d dl " + "buffer %d (RB unit %d, MCS %d, TBS %d) \n", + UE_id, + CC_id, + UE_info->UE_template[pCCid][UE_id].dl_buffer_total, + nb_rbs_required[CC_id][UE_id], + eNB_UE_stats->dlsch_mcs1, + TBS); + N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + + /* calculating required number of RBs for each UE */ + while (TBS < UE_info->UE_template[pCCid][UE_id].dl_buffer_total) { + nb_rbs_required[CC_id][UE_id] += min_rb_unit; + + if (nb_rbs_required[CC_id][UE_id] > N_RB_DL) { + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, N_RB_DL); + nb_rbs_required[CC_id][UE_id] = N_RB_DL; + break; + } + + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_rbs_required[CC_id][UE_id]); + } // end of while + + LOG_D(MAC, + "[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB " + "%d (TBS %d, mcs %d)\n", + Mod_id, + frameP, + UE_id, + CC_id, + min_rb_unit, + nb_rbs_required[CC_id][UE_id], + TBS, + eNB_UE_stats->dlsch_mcs1); + } + } + } +} + +void dlsch_scheduler_pre_processor_allocate_fairRR( + module_id_t Mod_id, + int UE_id, + uint8_t CC_id, + int N_RBG, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) { + int i; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + UE_sched_ctrl_t *ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; + int N_RB_DL = + to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); + + for (i = 0; i < N_RBG; i++) { + if (rballoc_sub[CC_id][i] != 0) + continue; + + if (ue_sched_ctl->rballoc_sub_UE[CC_id][i] != 0) + continue; + + if (nb_rbs_remaining[CC_id][UE_id] <= 0) + continue; + + if (ue_sched_ctl->pre_nb_available_rbs[CC_id] + >= nb_rbs_required[CC_id][UE_id]) + continue; + + if (ue_sched_ctl->dl_pow_off[CC_id] == 0) + continue; + + if ((i == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { + // Allocating last, smaller RBG + if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) { + rballoc_sub[CC_id][i] = 1; + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; + + nb_rbs_remaining[CC_id][UE_id] = + nb_rbs_remaining[CC_id][UE_id] - min_rb_unit + 1; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = + ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1; + } + } else { + // Allocating a standard-sized RBG + if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) { + rballoc_sub[CC_id][i] = 1; + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; + + nb_rbs_remaining[CC_id][UE_id] = + nb_rbs_remaining[CC_id][UE_id] - min_rb_unit; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = + ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit; + } + } + } +} // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, @@ -570,9 +894,8 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, uint16_t temp_total_rbs_count; unsigned char temp_total_ue_count; unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]; - uint8_t slice_allocation[MAX_NUM_CCs][N_RBG_MAX]; int UE_id, i; - uint16_t j,c; + uint16_t j; uint16_t nb_rbs_required[MAX_NUM_CCs][MAX_MOBILES_PER_ENB]; uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][MAX_MOBILES_PER_ENB]; // uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; @@ -581,7 +904,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, int min_rb_unit[MAX_NUM_CCs]; // uint16_t r1=0; uint8_t CC_id; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; int N_RB_DL; UE_sched_ctrl_t *ue_sched_ctl; // int rrc_status = RRC_IDLE; @@ -607,29 +930,27 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id); for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_list->active[i] != TRUE) + if (UE_info->active[i] != TRUE) continue; UE_id = i; // Initialize scheduling information for all active UEs - dlsch_scheduler_pre_processor_reset(Mod_id, - 0, - frameP, - subframeP, - min_rb_unit, - (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required, - rballoc_sub, - MIMO_mode_indicator, - mbsfn_flag); + dlsch_scheduler_pre_processor_reset_fairRR( + Mod_id, + frameP, + subframeP, + min_rb_unit, + (uint16_t(*)[MAX_MOBILES_PER_ENB])nb_rbs_required, + rballoc_sub, + MIMO_mode_indicator); } } #if (!defined(PRE_SCD_THREAD)) - // Store the DLSCH buffer for each logical channel - store_dlsch_buffer(Mod_id,0, frameP, subframeP); + // Store the DLSCH buffer for each logical channel and for PCCID (assume 0) + store_dlsch_buffer(Mod_id, 0, frameP, subframeP); // Calculate the number of RBs required by each UE on the basis of logical channel's buffer - assign_rbs_required(Mod_id, 0, frameP, subframeP, nb_rbs_required, - min_rb_unit); + assign_rbs_required_fairRR(Mod_id, frameP, subframeP, nb_rbs_required); #else memcpy(nb_rbs_required, pre_nb_rbs_required[dlsch_ue_select_tbl_in_use], sizeof(uint16_t)*MAX_NUM_CCs*MAX_MOBILES_PER_ENB); #endif @@ -678,7 +999,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, } rnti = dlsch_ue_select[CC_id].list[i].rnti; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); Round = ue_sched_ctl->round[CC_id][harq_pid]; @@ -689,23 +1010,15 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, nb_rbs_required_remaining[CC_id][UE_id] = cmin(average_rbs_per_user[CC_id], dlsch_ue_select[CC_id].list[i].nb_rb); } - /* slicing support has been introduced into the scheduler. Provide dummy - * data so that the preprocessor "simply works" */ - for (c = 0; c < MAX_NUM_CCs; ++c) - for (j = 0; j < N_RBG_MAX; ++j) - slice_allocation[c][j] = 1; - LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n "); - dlsch_scheduler_pre_processor_allocate (Mod_id, - UE_id, - CC_id, - N_RBG[CC_id], - min_rb_unit[CC_id], - (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required, - (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required_remaining, - rballoc_sub, - slice_allocation, - MIMO_mode_indicator); + dlsch_scheduler_pre_processor_allocate_fairRR( + Mod_id, + UE_id, + CC_id, + N_RBG[CC_id], + (uint16_t(*)[NUMBER_OF_UE_MAX])nb_rbs_required, + (uint16_t(*)[NUMBER_OF_UE_MAX])nb_rbs_required_remaining, + rballoc_sub); temp_total_rbs_count -= ue_sched_ctl->pre_nb_available_rbs[CC_id]; temp_total_ue_count--; @@ -782,7 +1095,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, } UE_id = dlsch_ue_select[CC_id].list[i].UE_id; - ue_sched_ctl = &RC.mac[Mod_id]->UE_list.UE_sched_ctrl[UE_id]; + ue_sched_ctl = &RC.mac[Mod_id]->UE_info.UE_sched_ctrl[UE_id]; //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id]; if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0) { @@ -835,7 +1148,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, uint16_t sdu_length_total = 0; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; // int continue_flag = 0; int32_t snr, target_snr; int32_t tpc = 1; @@ -933,7 +1246,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, N_RBG[CC_id] = to_rbg(cc[CC_id].mib->message.dl_Bandwidth); // store the global enb stats: - eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; + eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_info->num_UEs; eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb[CC_id]; eNB->eNB_stats[CC_id].total_available_prbs += @@ -973,12 +1286,12 @@ schedule_ue_spec_fairRR(module_id_t module_idP, rnti = UE_RNTI(module_idP,UE_id); if (rnti==NOT_A_RNTI) { - LOG_E(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n",UE_id,UE_list->num_UEs); + LOG_E(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n",UE_id,UE_info->num_UEs); continue; } - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; /* switch(get_tmode(module_idP,CC_id,UE_id)){ @@ -1005,7 +1318,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, UE_id, CC_id, cc[CC_id].tdd_Config->subframeAssignment, - UE_list); + UE_info); // update UL DAI after DLSCH scheduling set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); } @@ -1013,18 +1326,16 @@ schedule_ue_spec_fairRR(module_id_t module_idP, nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id]; harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); round = ue_sched_ctl->round[CC_id][harq_pid]; - UE_list->eNB_UE_stats[CC_id][UE_id].crnti = rnti; - UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status = - mac_eNB_get_rrc_status(module_idP, rnti); - UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; - UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round; + UE_info->eNB_UE_stats[CC_id][UE_id].crnti = rnti; + UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); + UE_info->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; + UE_info->eNB_UE_stats[CC_id][UE_id].harq_round = round; - if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_RECONFIGURED) { - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; + if (UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_RECONFIGURED) { + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; } - if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < - RRC_CONNECTED) + if (UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_CONNECTED) continue; sdu_length_total = 0; @@ -1043,13 +1354,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP, //eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); // store stats - //UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi; + //UE_info->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi; // initializing the rb allocation indicator for each UE for (j = 0; j < N_RBG[CC_id]; j++) { - UE_list-> - UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] - = 0; + UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0; } LOG_D(MAC, @@ -1057,33 +1366,31 @@ schedule_ue_spec_fairRR(module_id_t module_idP, module_idP, frameP, UE_id, CC_id, rnti, harq_pid, round, nb_available_rb, ue_sched_ctl->dl_cqi[CC_id], eNB_UE_stats->dlsch_mcs1, - UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); + UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status); /* process retransmission */ if (round != 8) { // get freq_allocation - nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; TBS = - get_TBS_DL(UE_list-> - UE_template[CC_id][UE_id].oldmcs1[harq_pid], + get_TBS_DL(UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid], nb_rb); if (nb_rb <= nb_available_rb) { if (cc[CC_id].tdd_Config != NULL) { - UE_list->UE_template[CC_id][UE_id].DAI++; + UE_info->UE_template[CC_id][UE_id].DAI++; update_ul_dci(module_idP, CC_id, rnti, - UE_list->UE_template[CC_id][UE_id]. - DAI,subframeP); + UE_info->UE_template[CC_id][UE_id].DAI,subframeP); LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", CC_id, subframeP, UE_id, - UE_list->UE_template[CC_id][UE_id].DAI); + UE_info->UE_template[CC_id][UE_id].DAI); } if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { for (j = 0; j < N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band - UE_list->UE_template[CC_id][UE_id]. + UE_info->UE_template[CC_id][UE_id]. rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; } @@ -1094,16 +1401,10 @@ schedule_ue_spec_fairRR(module_id_t module_idP, while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { if (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) { - if (UE_list-> - UE_template[CC_id] - [UE_id].rballoc_subband[harq_pid][j]) - printf - ("WARN: rballoc_subband not free for retrans?\n"); + if (UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]) + LOG_W(MAC, "WARN: rballoc_subband not free for retrans?\n"); - UE_list-> - UE_template[CC_id] - [UE_id].rballoc_subband[harq_pid][j] = - ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; if ((j == N_RBG[CC_id] - 1) && ((N_RB_DL[CC_id] == 25) || @@ -1127,7 +1428,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, eNB->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id]; for(j=0; jmu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]; + eNB->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]; } */ @@ -1164,36 +1465,23 @@ schedule_ue_spec_fairRR(module_id_t module_idP, harq_process = harq_pid; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // dont adjust power when retransmitting dl_config_pdu->dci_dl_pdu. - dci_dl_pdu_rel8.new_data_indicator_1 = - UE_list->UE_template[CC_id][UE_id]. - oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = - UE_list->UE_template[CC_id][UE_id]. - oldmcs1[harq_pid]; - dl_config_pdu->dci_dl_pdu. - dci_dl_pdu_rel8.redundancy_version_1 = - round & 3; + dci_dl_pdu_rel8.new_data_indicator_1 = UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round & 3; if (cc[CC_id].tdd_Config != NULL) { //TDD dl_config_pdu->dci_dl_pdu. - dci_dl_pdu_rel8.downlink_assignment_index = - (UE_list->UE_template[CC_id][UE_id].DAI - - 1) & 3; + dci_dl_pdu_rel8.downlink_assignment_index = (UE_info->UE_template[CC_id][UE_id].DAI - 1) & 3; LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", module_idP, CC_id, harq_pid, round, - (UE_list->UE_template[CC_id][UE_id].DAI - - 1), - UE_list-> - UE_template[CC_id][UE_id].oldmcs1 - [harq_pid]); + UE_info->UE_template[CC_id][UE_id].DAI - 1, + UE_info-> UE_template[CC_id][UE_id].oldmcs1[harq_pid]); } else { LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", module_idP, CC_id, harq_pid, round, - UE_list-> - UE_template[CC_id][UE_id].oldmcs1 - [harq_pid]); + UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid]); } if (!CCE_allocation_infeasible @@ -1205,12 +1493,14 @@ schedule_ue_spec_fairRR(module_id_t module_idP, dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - fill_nfapi_dlsch_config(eNB, dl_req, TBS, -1 + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], + TBS, + -1 /* retransmission, no pdu_index */ , rnti, 0, // type 0 allocation from 7.1.6 in 36.213 0, // virtual_resource_block_assignment_flag, unused here 0, // resource_block_coding, to be filled in later - getQm(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]), round & 3, // redundancy version + getQm(UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid]), round & 3, // redundancy version 1, // transport blocks 0, // transport block to codeword swap flag cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme @@ -1218,13 +1508,14 @@ schedule_ue_spec_fairRR(module_id_t module_idP, 1, // number of subbands // uint8_t codebook_index, 4, // UE category capacity - UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 0, // delta_power_offset for TM5 + UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 0, // delta_power_offset for TM5 0, // ngap 0, // nprb cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode 0, //number of PRBs treated as one subband, not used here 0 // number of beamforming vectors, not used here ); + dl_req->number_pdu++; LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", eNB->pdu_index[CC_id], round); @@ -1248,16 +1539,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP, S_DL_SCHEDULED, rnti); //eNB_UE_stats->dlsch_trials[round]++; - UE_list->eNB_UE_stats[CC_id][UE_id]. - num_retransmission += 1; - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx = - nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id]. - total_rbs_used_retx += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = - eNB_UE_stats->dlsch_mcs1; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2 = - eNB_UE_stats->dlsch_mcs1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_retransmission += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used_retx = nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx += nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; } else { LOG_D(MAC, "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", @@ -1289,7 +1575,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, header_len_dcch = 2; // 2 bytes DCCH SDU subheader if (TBS - ta_len - header_len_dcch > 0) { - rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, (TBS - ta_len - header_len_dcch),0, 0); // transport block set size + rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, 0, 0); // transport block set size sdu_lengths[0] = 0; if (rlc_status.bytes_in_buffer > 0) { // There is DCCH to transmit @@ -1297,7 +1583,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, "[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", module_idP, frameP, subframeP, CC_id, TBS - header_len_dcch); - sdu_lengths[0] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, TBS, //not used + sdu_lengths[0] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, + TBS - ta_len - header_len_dcch, (char *) &dlsch_buffer[0],0, 0 ); @@ -1369,11 +1656,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, module_idP, CC_id, frameP, subframeP, UE_id, rnti, sdu_lengths[0],rlc_status.bytes_in_buffer,rrc_release_info.num_UEs); sdu_length_total = sdu_lengths[0]; sdu_lcids[0] = DCCH; - UE_list->eNB_UE_stats[CC_id][UE_id]. - num_pdu_tx[DCCH] += 1; - UE_list-> - eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH] - += sdu_lengths[0]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH] += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH] += sdu_lengths[0]; num_sdus = 1; #ifdef DEBUG_eNB_SCHEDULER LOG_T(MAC, @@ -1394,7 +1678,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, // check for DCCH1 and update header information (assume 2 byte sub-header) if (TBS - ta_len - header_len_dcch - sdu_length_total > 0) { - rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, (TBS - ta_len - header_len_dcch - sdu_length_total),0, 0 + rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, 0, 0 ); // transport block set size less allocations for timing advance and // DCCH SDU sdu_lengths[num_sdus] = 0; @@ -1404,7 +1688,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", module_idP, frameP, CC_id, TBS - header_len_dcch - sdu_length_total); - sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, TBS, //not used + sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, + TBS - ta_len - header_len_dcch - sdu_length_total, (char *) &dlsch_buffer[sdu_length_total],0, 0 ); T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), @@ -1414,11 +1699,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, sdu_lcids[num_sdus] = DCCH1; sdu_length_total += sdu_lengths[num_sdus]; header_len_dcch += 2; - UE_list->eNB_UE_stats[CC_id][UE_id]. - num_pdu_tx[DCCH1] += 1; - UE_list-> - eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] - += sdu_lengths[num_sdus]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1] += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; num_sdus++; #ifdef DEBUG_eNB_SCHEDULER LOG_T(MAC, @@ -1460,7 +1742,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS - ta_len - header_len_dcch - sdu_length_total - header_len_dtch, 0, 0 + 0, 0 ); if (rlc_status.bytes_in_buffer > 0) { @@ -1477,7 +1759,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS, //not used + TBS - ta_len - header_len_dcch - sdu_length_total - header_len_dtch, (char *)&dlsch_buffer[sdu_length_total], 0, 0 ); T(T_ENB_MAC_UE_DL_SDU, @@ -1495,8 +1777,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, lcid); sdu_lcids[num_sdus] = lcid; sdu_length_total += sdu_lengths[num_sdus]; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[num_sdus]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[num_sdus]; if (sdu_lengths[num_sdus] < 128) { header_len_dtch--; @@ -1504,7 +1786,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, } num_sdus++; - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; } else { // no data for this LCID header_len_dtch -= 3; } @@ -1557,9 +1839,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { for (j = 0; j < N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band - UE_list->UE_template[CC_id][UE_id]. - rballoc_subband[harq_pid][j] = - ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; } } else { nb_rb_temp = nb_rb; @@ -1568,10 +1848,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { if (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) { - UE_list-> - UE_template[CC_id] - [UE_id].rballoc_subband[harq_pid][j] = - ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; if ((j == N_RBG[CC_id] - 1) && ((N_RB_DL[CC_id] == 25) || @@ -1650,7 +1927,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, } #endif - offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus + offset = generate_dlsch_header((unsigned char *) UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus sdu_lengths, // sdu_lcids, 255, // no drx ta_update, // timing advance @@ -1679,20 +1956,20 @@ schedule_ue_spec_fairRR(module_id_t module_idP, LOG_T(MAC, "\n"); #endif // cycle through SDUs and place in dlsch_buffer - memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total); + memcpy(&UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total); // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); // fill remainder of DLSCH with random data for (j=0; j<(TBS-sdu_length_total-offset); j++) { - UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff); + UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff); } - trace_pdu(DIRECTION_DOWNLINK, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + trace_pdu(DIRECTION_DOWNLINK, (uint8_t *)UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS, module_idP, WS_RA_RNTI, UE_RNTI(module_idP, UE_id), eNB->frame, eNB->subframe,0,0); T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), - T_INT(harq_pid), T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS)); - UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb; + T_INT(harq_pid), T_BUFFER(UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS)); + UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb; add_ue_dlsch_info(module_idP, CC_id, UE_id, @@ -1702,37 +1979,37 @@ schedule_ue_spec_fairRR(module_id_t module_idP, // store stats eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total; eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=mcs; - UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS; - UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS- sdu_length_total; - UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total; - UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS; - UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1; + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=mcs; + UE_info->eNB_UE_stats[CC_id][UE_id].TBS = TBS; + UE_info->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS- sdu_length_total; + UE_info->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total; + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS; + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1; if (cc[CC_id].tdd_Config != NULL) { // TDD - UE_list->UE_template[CC_id][UE_id].DAI++; - update_ul_dci(module_idP,CC_id,rnti,UE_list->UE_template[CC_id][UE_id].DAI,subframeP); + UE_info->UE_template[CC_id][UE_id].DAI++; + update_ul_dci(module_idP,CC_id,rnti,UE_info->UE_template[CC_id][UE_id].DAI,subframeP); } // do PUCCH power control // this is the snr - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; /* Unit is not dBm, it's special from nfapi */ snr = (5 * ue_sched_ctl->pucch1_snr[CC_id] - 640) / 10; target_snr = eNB->puCch10xSnr / 10; // this assumes accumulated tpc // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out - int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; + int32_t framex10psubframe = UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around if (ue_sched_ctl->pucch1_cqi_update[CC_id] == 1) { ue_sched_ctl->pucch1_cqi_update[CC_id] = 0; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP; + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP; + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP; if (snr > target_snr + 4) { tpc = 0; //-1 @@ -1767,7 +2044,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1-UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; //deactivate second codeword @@ -1775,10 +2052,10 @@ schedule_ue_spec_fairRR(module_id_t module_idP, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; if (cc[CC_id].tdd_Config != NULL) { //TDD - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (UE_info->UE_template[CC_id][UE_id].DAI-1)&3; LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", module_idP,CC_id,harq_pid, - (UE_list->UE_template[CC_id][UE_id].DAI-1), + (UE_info->UE_template[CC_id][UE_id].DAI-1), mcs); } else { LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", @@ -1797,13 +2074,13 @@ schedule_ue_spec_fairRR(module_id_t module_idP, // Toggle NDI for next time LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", CC_id, frameP,subframeP,UE_id, - rnti,harq_pid,UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]); - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs; - UE_list->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); - fill_nfapi_dlsch_config(eNB,dl_req, + rnti,harq_pid,UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]); + UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs; + UE_info->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], TBS, eNB->pdu_index[CC_id], rnti, @@ -1819,7 +2096,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, 1, // number of subbands // uint8_t codebook_index, 4, // UE category capacity - UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 0, // delta_power_offset for TM5 0, // ngap 0, // nprb @@ -1827,11 +2104,12 @@ schedule_ue_spec_fairRR(module_id_t module_idP, 0, //number of PRBs treated as one subband, not used here 0 // number of beamforming vectors, not used here ); + dl_req->number_pdu++; eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, (frameP*10)+subframeP, TBS, eNB->pdu_index[CC_id], - eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]); + eNB->UE_info.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]); LOG_D(MAC,"Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n",eNB->pdu_index[CC_id]); eNB->pdu_index[CC_id]++; program_dlsch_acknak(module_idP,CC_id,UE_id,frameP,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); @@ -1876,7 +2154,7 @@ fill_DLSCH_dci_fairRR( int i; int CC_id; eNB_MAC_INST *eNB =RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; int N_RBG; int N_RB_DL; COMMON_channels_t *cc; @@ -1912,11 +2190,11 @@ fill_DLSCH_dci_fairRR( eNB_dlsch_info[module_idP][CC_id][UE_id].status = S_DL_WAITING; rnti = UE_RNTI(module_idP,UE_id); harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; /// Synchronizing rballoc with rballoc_sub for(i=0; iUE_template[CC_id][UE_id].rballoc_subband[harq_pid][i]; + rballoc_sub[i] = UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i]; } nfapi_dl_config_request_t *DL_req = &RC.mac[module_idP]->DL_req[0]; @@ -1962,7 +2240,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( uint8_t first_ue_total[MAX_NUM_CCs][20]; uint8_t first_ue_id[MAX_NUM_CCs][20]; uint8_t ul_inactivity_num[MAX_NUM_CCs]; - uint8_t ul_inactivity_id[MAX_NUM_CCs][20]; + uint8_t ul_inactivity_id[MAX_NUM_CCs][20]={0}; // LTE_DL_FRAME_PARMS *frame_parms; uint8_t ulsch_ue_max_num[MAX_NUM_CCs]; uint16_t saved_ulsch_dci[MAX_NUM_CCs]; @@ -1970,7 +2248,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( UE_sched_ctrl_t *UE_sched_ctl = NULL; uint8_t cc_id_flag[MAX_NUM_CCs]; uint8_t harq_pid = 0,round = 0; - UE_list_t *UE_list= &eNB->UE_list; + UE_info_t *UE_info= &eNB->UE_info; uint8_t aggregation; int format_flag; nfapi_hi_dci0_request_body_t *HI_DCI0_req; @@ -1989,7 +2267,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( // UE round >0 for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) { - if (UE_list->active[UE_id] == FALSE) + if (UE_info->active[UE_id] == FALSE) continue; rnti = UE_RNTI(module_idP,UE_id); @@ -1999,10 +2277,10 @@ void ulsch_scheduler_pre_ue_select_fairRR( CC_id = UE_PCCID(module_idP,UE_id); - if (UE_list->UE_template[CC_id][UE_id].configured == FALSE) + if (UE_info->UE_template[CC_id][UE_id].configured == FALSE) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) + if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; // UL DCI @@ -2026,12 +2304,12 @@ void ulsch_scheduler_pre_ue_select_fairRR( //harq_pid harq_pid = subframe2harqpid(cc,(frameP+(sched_subframePUE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; + round = UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; if ( round > 0 ) { hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); + aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { cc_id_flag[CC_id] = 1; @@ -2042,8 +2320,8 @@ void ulsch_scheduler_pre_ue_select_fairRR( hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; HI_DCI0_req->number_of_dci++; ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_RETRANS; - ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = eNB->UE_list.UE_template[CC_id][UE_id].first_rb_ul[harq_pid]; - ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = eNB->UE_list.UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = eNB->UE_info.UE_template[CC_id][UE_id].first_rb_ul[harq_pid]; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = eNB->UE_info.UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = UE_id; ulsch_ue_select[CC_id].ue_num++; continue; @@ -2051,7 +2329,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( } // - int bytes_to_schedule = UE_list->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_list->UE_template[CC_id][UE_id].scheduled_ul_bytes; + int bytes_to_schedule = UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes; if (bytes_to_schedule < 0) bytes_to_schedule = 0; @@ -2063,14 +2341,14 @@ void ulsch_scheduler_pre_ue_select_fairRR( continue; } - if ( UE_list->UE_template[CC_id][UE_id].ul_SR > 0 ) { + if ( UE_info->UE_template[CC_id][UE_id].ul_SR > 0 ) { first_ue_id[CC_id][ue_first_num[CC_id]]= UE_id; first_ue_total[CC_id] [ue_first_num[CC_id]] = 0; ue_first_num[CC_id]++; continue; } - UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); if ( ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) || @@ -2083,7 +2361,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( } /*if ( (ulsch_ue_select[CC_id].ue_num+ul_inactivity_num[CC_id] ) < ulsch_ue_max_num[CC_id] ) { - UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; uint8_t ul_period = 0; if (cc->tdd_Config) { ul_period = 50; @@ -2113,7 +2391,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; rnti = UE_RNTI(module_idP,first_ue_id[CC_id][temp]); - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[first_ue_id[CC_id][temp]].dl_cqi[CC_id],format0); + aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_info->UE_sched_ctrl[first_ue_id[CC_id][temp]].dl_cqi[CC_id],format0); if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { cc_id_flag[CC_id] = 1; @@ -2132,7 +2410,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( } for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) { - if (UE_list->active[UE_id] == FALSE) + if (UE_info->active[UE_id] == FALSE) continue; rnti = UE_RNTI(module_idP,UE_id); @@ -2145,10 +2423,10 @@ void ulsch_scheduler_pre_ue_select_fairRR( if (UE_id > last_ulsch_ue_id[CC_id]) continue; - if (UE_list->UE_template[CC_id][UE_id].configured == FALSE) + if (UE_info->UE_template[CC_id][UE_id].configured == FALSE) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) + if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) { @@ -2176,19 +2454,19 @@ void ulsch_scheduler_pre_ue_select_fairRR( HI_DCI0_req = &eNB->HI_DCI0_req[CC_id][subframeP].hi_dci0_request_body; //SR BSR - UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - int bytes_to_schedule = UE_list->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_list->UE_template[CC_id][UE_id].scheduled_ul_bytes; + UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; + int bytes_to_schedule = UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes; if (bytes_to_schedule < 0) bytes_to_schedule = 0; rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); - if ( (bytes_to_schedule > 0) || (UE_list->UE_template[CC_id][UE_id].ul_SR > 0) || + if ( (bytes_to_schedule > 0) || (UE_info->UE_template[CC_id][UE_id].ul_SR > 0) || ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) || ((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(rrc_status < RRC_CONNECTED)) || ((UE_sched_ctl->cqi_req_timer>300)&&((rrc_status >= RRC_CONNECTED))) ) { hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); + aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { cc_id_flag[CC_id] = 1; @@ -2202,7 +2480,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( if(bytes_to_schedule > 0) ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = bytes_to_schedule; - else if(UE_list->UE_template[CC_id][UE_id].ul_SR > 0) + else if(UE_info->UE_template[CC_id][UE_id].ul_SR > 0) ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = 0; ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = UE_id; @@ -2213,7 +2491,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( //inactivity UE /* if ( (ulsch_ue_select[CC_id].ue_num+ul_inactivity_num[CC_id]) < ulsch_ue_max_num[CC_id] ) { - UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; uint8_t ul_period = 0; if (cc->tdd_Config) { ul_period = 50; @@ -2242,7 +2520,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; rnti = UE_RNTI(module_idP,ul_inactivity_id[CC_id][temp]); - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[ul_inactivity_id[CC_id][temp]].dl_cqi[CC_id],format0); + aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_info->UE_sched_ctrl[ul_inactivity_id[CC_id][temp]].dl_cqi[CC_id],format0); if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { cc_id_flag[CC_id] = 1; @@ -2284,7 +2562,7 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]) { int CC_id,ulsch_ue_num; eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list= &eNB->UE_list; + UE_info_t *UE_info= &eNB->UE_info; UE_TEMPLATE *UE_template = NULL; LTE_DL_FRAME_PARMS *frame_parms = NULL; uint8_t ue_num_temp; @@ -2383,9 +2661,9 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, } } } else { - UE_template = &UE_list->UE_template[CC_id][UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; - if ( UE_list->UE_sched_ctrl[UE_id].phr_received == 1 ) { + if ( UE_info->UE_sched_ctrl[UE_id].phr_received == 1 ) { mcs = 20; } else { mcs = 10; @@ -2421,9 +2699,9 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, if ( rb_table[rb_table_index] <= average_rbs ) { // assigne RBS( nb_rb) first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index]; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = rb_table[rb_table_index]; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = rb_table[rb_table_index]; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; } if ( rb_table[rb_table_index] > average_rbs ) { @@ -2437,31 +2715,31 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, } first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index]; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = rb_table[rb_table_index]; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = rb_table[rb_table_index]; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; } } else { if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) { // assigne RBS( 6 RBs) first_rb[CC_id] = first_rb[CC_id] + 6; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 6; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 5; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 6; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 5; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } else { // assigne RBS( 3 RBs) first_rb[CC_id] = first_rb[CC_id] + 3; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 3; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } } } else if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE ) { // assigne RBS( 3 RBs) first_rb[CC_id] = first_rb[CC_id] + 3; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 3; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } } @@ -2641,7 +2919,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, int N_RB_UL; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc; - UE_list_t *UE_list=&eNB->UE_list; + UE_info_t *UE_info=&eNB->UE_info; UE_TEMPLATE *UE_template; UE_sched_ctrl_t *UE_sched_ctrl; int sched_frame=frameP; @@ -2750,8 +3028,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, continue; } - UE_template = &UE_list->UE_template[CC_id][UE_id]; - UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = subframe2harqpid(cc,sched_frame,sched_subframeP); rnti = UE_RNTI(CC_id,UE_id); aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); @@ -2844,9 +3122,9 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, UE_sched_ctrl->cqi_req_timer); ndi = 1-UE_template->oldNDI_UL[harq_pid]; UE_template->oldNDI_UL[harq_pid]=ndi; - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul; UE_template->mcs_UL[harq_pid] = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS if (UE_template->pre_allocated_rb_table_index_ul >=0) { @@ -2856,10 +3134,10 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, rb_table_index=5; // for PHR } - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=UE_template->mcs_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=UE_template->mcs_UL[harq_pid]; UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],rb_table[rb_table_index]); - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index]; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]), T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi)); @@ -2877,7 +3155,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, UE_template->cqi_req[harq_pid] = cqi_req; UE_sched_ctrl->ul_scheduled |= (1<head) + if (UE_id == UE_info->list.head) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,UE_sched_ctrl->ul_scheduled); // adjust total UL buffer status by TBS, wait for UL sdus to do final update @@ -3019,8 +3297,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb), T_INT(ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb), T_INT(round)); - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; uint8_t mcs_rv = 0; if(rvidx_tab[round&3]==1) { @@ -3032,7 +3310,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, } UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb); - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED) LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, TBS %d, harq_pid %d)\n", diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h index 5355a614a6..880e60ec19 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h @@ -85,6 +85,30 @@ void dlsch_scheduler_pre_ue_select_fairRR( uint16_t nb_rbs_required[MAX_NUM_CCs][MAX_MOBILES_PER_ENB], DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]); +void dlsch_scheduler_pre_processor_reset_fairRR( + module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + int min_rb_unit[NFAPI_CC_MAX], + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], + uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); + +void assign_rbs_required_fairRR( + module_id_t Mod_id, + frame_t frameP, + sub_frame_t subframe, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]); + +void dlsch_scheduler_pre_processor_allocate_fairRR( + module_id_t Mod_id, + int UE_id, + uint8_t CC_id, + int N_RBG, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); + void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, frame_t frameP, sub_frame_t subframeP, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c index 2953c8e70b..eb5d78fd3f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c @@ -714,13 +714,11 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, mbms_rab_id = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9; rlc_status = - mac_rlc_status_ind(module_idP, 0/*0xfffd*/, frameP, subframeP, + mac_rlc_status_ind(module_idP, 0xfffd, frameP, subframeP, module_idP, ENB_FLAG_YES, MBMS_FLAG_YES, cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, //MTCH, - TBS - header_len_mcch - header_len_msi - - sdu_length_total - header_len_mtch - ,0, 0 + 0, 0 ); bytes_in_buffer = rlc_status.bytes_in_buffer; @@ -773,7 +771,8 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0/*0xfffd*/, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0, //not used + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0xfffd, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, + TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch, (char *) &mch_buffer[sdu_length_total] ,0, @@ -1554,13 +1553,11 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, mbms_rab_id = cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9; rlc_status = - mac_rlc_status_ind(module_idP, 0/*0xfffd*/, frameP, subframeP, + mac_rlc_status_ind(module_idP, 0xfffd, frameP, subframeP, module_idP, ENB_FLAG_YES, MBMS_FLAG_YES, cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, //MTCH, - TBS - header_len_mcch - header_len_msi - - sdu_length_total - header_len_mtch - ,0, 0 + 0, 0 ); bytes_in_buffer = rlc_status.bytes_in_buffer; @@ -1579,7 +1576,8 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0/*0xfffd*/, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0, //not used + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0xfffd, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, + TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch, (char *) &mch_buffer[sdu_length_total] ,0, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c index 647db3f624..689db8e208 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c @@ -133,16 +133,15 @@ schedule_ue_spec_phy_test( /* LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", CC_id, frameP,subframeP,UE_id, - rnti,harq_pid,UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]); + rnti,harq_pid,UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]); - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs; - UE_list->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); + UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs; + UE_info->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); */ - fill_nfapi_dlsch_config(eNB, - dl_req, + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], TBS, eNB->pdu_index[CC_id], rnti, @@ -166,11 +165,12 @@ schedule_ue_spec_phy_test( 0, //number of PRBs treated as one subband, not used here 0 // number of beamforming vectors, not used here ); + dl_req->number_pdu++; eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, (frameP*10)+subframeP, TBS, eNB->pdu_index[CC_id], - eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]); + eNB->UE_info.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]); } else { LOG_W(MAC,"[eNB_scheduler_phytest] DCI allocation infeasible!\n"); } @@ -192,7 +192,7 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s int N_RB_UL; eNB_MAC_INST *mac = RC.mac[module_idP]; COMMON_channels_t *cc = &mac->common_channels[0]; - UE_list_t *UE_list=&mac->UE_list; + UE_info_t *UE_info=&mac->UE_info; UE_TEMPLATE *UE_template; UE_sched_ctrl_t *UE_sched_ctrl; int sched_frame=frameP; @@ -231,8 +231,8 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s first_rb[CC_id] = 1; // loop over all active UEs // if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel - UE_template = &UE_list->UE_template[CC_id][UE_id]; - UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = subframe2harqpid(&cc[CC_id],sched_frame,sched_subframe); RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP] = UE_template->TBS_UL[harq_pid]; //power control @@ -242,15 +242,15 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s // new transmission ndi = 1-UE_template->oldNDI_UL[harq_pid]; UE_template->oldNDI_UL[harq_pid]=ndi; - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = mcs; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = mcs; UE_template->mcs_UL[harq_pid] = mcs;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = mcs; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = mcs; // buffer_occupancy = UE_template->ul_total_buffer; UE_template->TBS_UL[harq_pid] = get_TBS_UL(mcs,nb_rb); - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = get_TBS_UL(mcs,nb_rb); + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = get_TBS_UL(mcs,nb_rb); // buffer_occupancy -= TBS; // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB) //store for possible retransmission diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index e76e6b24ba..78d6f6a3d7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1169,14 +1169,14 @@ program_dlsch_acknak(module_id_t module_idP, { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; rnti_t rnti = UE_RNTI(module_idP, UE_idP); nfapi_ul_config_request_body_t *ul_req; nfapi_ul_config_request_pdu_t *ul_config_pdu; int use_simultaneous_pucch_pusch = 0; nfapi_ul_config_ulsch_harq_information *ulsch_harq_information = NULL; nfapi_ul_config_harq_information *harq_information = NULL; - struct LTE_PhysicalConfigDedicated__ext2 *ext2 = UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2; + struct LTE_PhysicalConfigDedicated__ext2 *ext2 = UE_info->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2; if (ext2 && ext2->pucch_ConfigDedicated_v1020 && @@ -1363,12 +1363,12 @@ fill_nfapi_ulsch_harq_information(module_id_t module_ { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; int UE_id = find_UE_id(module_idP, rntiP); nfapi_ul_config_ulsch_harq_information_rel10_t *harq_information_rel10 = &harq_information->harq_information_rel10; AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n"); - AssertFatal(UE_list != NULL, "UE_list is null\n"); - LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated; + AssertFatal(UE_info != NULL, "UE_info is null\n"); + LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated; AssertFatal(physicalConfigDedicated != NULL, "physicalConfigDedicated for rnti %x is null\n", rntiP); struct LTE_PUSCH_ConfigDedicated *puschConfigDedicated = physicalConfigDedicated->pusch_ConfigDedicated; @@ -1468,14 +1468,14 @@ fill_nfapi_harq_information(module_id_t module_idP, { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; int UE_id = find_UE_id(module_idP, rntiP); AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n"); - AssertFatal(UE_list != NULL, "UE_list is null\n"); + AssertFatal(UE_info != NULL, "UE_info is null\n"); harq_information->harq_information_rel11.tl.tag = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG; harq_information->harq_information_rel11.num_ant_ports = 1; - LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated; + LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated; struct LTE_PUCCH_ConfigDedicated *pucch_ConfigDedicated = NULL; if (physicalConfigDedicated != NULL) pucch_ConfigDedicated = physicalConfigDedicated->pucch_ConfigDedicated; @@ -1489,7 +1489,7 @@ fill_nfapi_harq_information(module_id_t module_idP, case 6: case 7: if (cc->tdd_Config != NULL) { - // AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated != NULL, + // AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated != NULL, // "pucch_ConfigDedicated is null for TDD!\n"); if (physicalConfigDedicated != NULL && pucch_ConfigDedicated != NULL && pucch_ConfigDedicated->tdd_AckNackFeedbackMode != NULL && @@ -1619,15 +1619,14 @@ fill_nfapi_mch_config(nfapi_dl_config_request_body_t *dl_req, //------------------------------------------------------------------------------ void -fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, - nfapi_dl_config_request_body_t *dl_req, +fill_nfapi_dlsch_config(nfapi_dl_config_request_pdu_t *dl_config_pdu, uint16_t length, int16_t pdu_index, uint16_t rnti, uint8_t resource_allocation_type, uint8_t virtual_resource_block_assignment_flag, - uint16_t resource_block_coding, + uint32_t resource_block_coding, uint8_t modulation, uint8_t redundancy_version, uint8_t transport_blocks, @@ -1646,7 +1645,6 @@ fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, uint8_t num_bf_vector) //------------------------------------------------------------------------------ { - nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); @@ -1673,7 +1671,6 @@ fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = transmission_mode; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = num_bf_prb_per_subband; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = num_bf_vector; - dl_req->number_pdu++; return; } @@ -1879,8 +1876,7 @@ mpdcch_sf_condition(eNB_MAC_INST *eNB, break; case TYPEUESPEC: - epdcch_setconfig_r11 = - eNB->UE_list.UE_template[CC_id][UE_id].physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0]; + epdcch_setconfig_r11 = eNB->UE_info.UE_template[CC_id][UE_id].physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0]; AssertFatal(epdcch_setconfig_r11 != NULL, " epdcch_setconfig_r11 is null for UE specific \n"); AssertFatal(epdcch_setconfig_r11->ext2 != NULL, " ext2 doesn't exist in epdcch config ' \n"); @@ -1988,11 +1984,11 @@ find_UE_id(module_id_t mod_idP, //------------------------------------------------------------------------------ { int UE_id; - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id] == TRUE) { - if (UE_list->UE_template[UE_PCCID(mod_idP, UE_id)][UE_id].rnti == rntiP) { + if (UE_info->active[UE_id] == TRUE) { + if (UE_info->UE_template[UE_PCCID(mod_idP, UE_id)][UE_id].rnti == rntiP) { return UE_id; } } @@ -2027,7 +2023,7 @@ find_RA_id(module_id_t mod_idP, //------------------------------------------------------------------------------ int -UE_num_active_CC(UE_list_t *listP, +UE_num_active_CC(UE_info_t *listP, int ue_idP) //------------------------------------------------------------------------------ { @@ -2040,7 +2036,7 @@ UE_PCCID(module_id_t mod_idP, int ue_idP) //------------------------------------------------------------------------------ { - return (RC.mac[mod_idP]->UE_list.pCC_id[ue_idP]); + return (RC.mac[mod_idP]->UE_info.pCC_id[ue_idP]); } //------------------------------------------------------------------------------ @@ -2051,7 +2047,7 @@ UE_RNTI(module_id_t mod_idP, { if (!RC.mac || !RC.mac[mod_idP]) return 0; - rnti_t rnti = RC.mac[mod_idP]->UE_list.UE_template[UE_PCCID(mod_idP, + rnti_t rnti = RC.mac[mod_idP]->UE_info.UE_template[UE_PCCID(mod_idP, ue_idP)][ue_idP].rnti; if (rnti > 0) { @@ -2069,7 +2065,7 @@ is_UE_active(module_id_t mod_idP, int ue_idP) //------------------------------------------------------------------------------ { - return (RC.mac[mod_idP]->UE_list.active[ue_idP]); + return (RC.mac[mod_idP]->UE_info.active[ue_idP]); } //------------------------------------------------------------------------------ @@ -2122,28 +2118,46 @@ get_aggregation(uint8_t bw_index, //------------------------------------------------------------------------------ /* - * Dump the UL or DL UE_list into LOG_T(MAC) + * Dump the UE_list into LOG_T(MAC) */ void -dump_ue_list(UE_list_t *listP, - int ul_flag) +dump_ue_list(UE_list_t *listP) { + for (int j = listP->head; j >= 0; j = listP->next[j]) + LOG_T(MAC, "DL list node %d => %d\n", j, listP->next[j]); +} + //------------------------------------------------------------------------------ -{ - if (ul_flag == 0) { - for (int j = listP->head; j >= 0; j = listP->next[j]) { - LOG_T(MAC, "DL list node %d => %d\n", - j, - listP->next[j]); - } +/* + * Add a UE to UE_list listP + */ +inline void add_ue_list(UE_list_t *listP, int UE_id) { + if (listP->head == -1) { + listP->head = UE_id; + listP->next[UE_id] = -1; } else { - for (int j = listP->head_ul; j >= 0; j = listP->next_ul[j]) { - LOG_T(MAC, "UL list node %d => %d\n", - j, - listP->next_ul[j]); - } + int i = listP->head; + while (listP->next[i] >= 0) + i = listP->next[i]; + listP->next[i] = UE_id; + listP->next[UE_id] = -1; + } +} + +//------------------------------------------------------------------------------ +/* + * Remove a UE from the UE_list listP, return the previous element + */ +inline int remove_ue_list(UE_list_t *listP, int UE_id) { + listP->next[UE_id] = -1; + if (listP->head == UE_id) { + listP->head = listP->next[UE_id]; + return -1; } - return; + int previous = prev(listP, UE_id); + if (previous != -1) + listP->next[previous] = listP->next[UE_id]; + return previous; } //------------------------------------------------------------------------------ @@ -2158,50 +2172,47 @@ add_new_ue(module_id_t mod_idP, { int UE_id; int i, j; - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - LOG_D(MAC, "[eNB %d, CC_id %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n", + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; + LOG_D(MAC, "[eNB %d, CC_id %d] Adding UE with rnti %x (prev. num_UEs %d)\n", mod_idP, cc_idP, rntiP, - UE_list->avail, - UE_list->num_UEs); - dump_ue_list(UE_list, 0); + UE_info->num_UEs); for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { - if (UE_list->active[i] == TRUE) + if (UE_info->active[i] == TRUE) continue; UE_id = i; - memset(&UE_list->UE_template[cc_idP][UE_id], 0, sizeof(UE_TEMPLATE)); - UE_list->UE_template[cc_idP][UE_id].rnti = rntiP; - UE_list->UE_template[cc_idP][UE_id].configured = FALSE; - UE_list->numactiveCCs[UE_id] = 1; - UE_list->numactiveULCCs[UE_id] = 1; - UE_list->pCC_id[UE_id] = cc_idP; - UE_list->ordered_CCids[0][UE_id] = cc_idP; - UE_list->ordered_ULCCids[0][UE_id] = cc_idP; - UE_list->num_UEs++; - UE_list->active[UE_id] = TRUE; + memset(&UE_info->UE_template[cc_idP][UE_id], 0, sizeof(UE_TEMPLATE)); + UE_info->UE_template[cc_idP][UE_id].rnti = rntiP; + UE_info->UE_template[cc_idP][UE_id].configured = FALSE; + UE_info->numactiveCCs[UE_id] = 1; + UE_info->numactiveULCCs[UE_id] = 1; + UE_info->pCC_id[UE_id] = cc_idP; + UE_info->ordered_CCids[0][UE_id] = cc_idP; + UE_info->ordered_ULCCids[0][UE_id] = cc_idP; + UE_info->num_UEs++; + UE_info->active[UE_id] = TRUE; + add_ue_list(&UE_info->list, UE_id); + dump_ue_list(&UE_info->list); if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ? - UE_list->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0; - UE_list->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type; - memset((void *) &UE_list->UE_sched_ctrl[UE_id], + UE_info->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0; + UE_info->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type; + memset((void *) &UE_info->UE_sched_ctrl[UE_id], 0, sizeof(UE_sched_ctrl_t)); - memset((void *) &UE_list->eNB_UE_stats[cc_idP][UE_id], + memset((void *) &UE_info->eNB_UE_stats[cc_idP][UE_id], 0, sizeof(eNB_UE_STATS)); - UE_list->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; - /* default slice in case there was something different */ - UE_list->assoc_dl_slice_idx[UE_id] = 0; - UE_list->assoc_ul_slice_idx[UE_id] = 0; - UE_list->UE_sched_ctrl[UE_id].ta_update = 31; + UE_info->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; + UE_info->UE_sched_ctrl[UE_id].ta_update = 31; for (j = 0; j < 8; j++) { - UE_list->UE_template[cc_idP][UE_id].oldNDI[j] = 0; - UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = 0; - UE_list->UE_sched_ctrl[UE_id].round[cc_idP][j] = 8; - UE_list->UE_sched_ctrl[UE_id].round_UL[cc_idP][j] = 0; + UE_info->UE_template[cc_idP][UE_id].oldNDI[j] = 0; + UE_info->UE_template[cc_idP][UE_id].oldNDI_UL[j] = 0; + UE_info->UE_sched_ctrl[UE_id].round[cc_idP][j] = 8; + UE_info->UE_sched_ctrl[UE_id].round_UL[cc_idP][j] = 0; } eNB_ulsch_info[mod_idP][cc_idP][UE_id].status = S_UL_WAITING; @@ -2211,15 +2222,11 @@ add_new_ue(module_id_t mod_idP, UE_id, cc_idP, rntiP); - dump_ue_list(UE_list, - 0); return (UE_id); } - // printf("MAC: cannot add new UE for rnti %x\n", rntiP); LOG_E(MAC, "error in add_new_ue(), could not find space in UE_list, Dumping UE list\n"); - dump_ue_list(UE_list, - 0); + dump_ue_list(&UE_info->list); return -1; } @@ -2232,7 +2239,7 @@ rrc_mac_remove_ue(module_id_t mod_idP, rnti_t rntiP) //------------------------------------------------------------------------------ { - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; int UE_id = find_UE_id(mod_idP, rntiP); eNB_UE_STATS *ue_stats = NULL; int pCC_id = -1; @@ -2248,37 +2255,14 @@ rrc_mac_remove_ue(module_id_t mod_idP, UE_id, pCC_id, rntiP); - dump_ue_list(UE_list, 0); // DL list displayed in LOG_T(MAC) - UE_list->active[UE_id] = FALSE; - UE_list->num_UEs--; + UE_info->active[UE_id] = FALSE; + UE_info->num_UEs--; - /* If present, remove UE from DL list */ - if (UE_list->head == UE_id) { - UE_list->head = UE_list->next[UE_id]; - } else { - int previous = prev(UE_list, UE_id, 0); - - if (previous != -1) { - UE_list->next[previous] = UE_list->next[UE_id]; - } - } - - /* If present, remove UE from UL list */ - if (UE_list->head_ul == UE_id) { - UE_list->head_ul = UE_list->next_ul[UE_id]; - } else { - int previous = prev(UE_list, UE_id, 1); - - if (previous != -1) { - UE_list->next_ul[previous] = UE_list->next_ul[UE_id]; - } - } + remove_ue_list(&UE_info->list, UE_id); /* Clear all remaining pending transmissions */ - memset(&UE_list->UE_template[pCC_id][UE_id], - 0, - sizeof(UE_TEMPLATE)); - ue_stats = &UE_list->eNB_UE_stats[pCC_id][UE_id]; + memset(&UE_info->UE_template[pCC_id][UE_id], 0, sizeof(UE_TEMPLATE)); + ue_stats = &UE_info->eNB_UE_stats[pCC_id][UE_id]; ue_stats->total_rbs_used = 0; ue_stats->total_rbs_used_retx = 0; @@ -2355,166 +2339,19 @@ rrc_mac_remove_ue(module_id_t mod_idP, /* * Returns the previous UE_id in the scheduling list in UL or DL */ -int -prev(UE_list_t *listP, - int nodeP, - int ul_flag) -//------------------------------------------------------------------------------ -{ - if (ul_flag == 0) { - if (nodeP == listP->head) { - return nodeP; - } +inline int prev(UE_list_t *listP, int nodeP) { + if (nodeP == listP->head) + return -1; /* there is no previous of the head */ - for (int j = listP->head; j >= 0; j = listP->next[j]) { - if (listP->next[j] == nodeP) { - return j; - } - } - } else { - if (nodeP == listP->head_ul) { - return nodeP; - } + for (int j = listP->head; j >= 0; j = listP->next[j]) + if (listP->next[j] == nodeP) + return j; - for (int j = listP->head_ul; j >= 0; j = listP->next_ul[j]) { - if (listP->next_ul[j] == nodeP) { - return j; - } - } - } - - LOG_E(MAC, "error in prev(), could not find previous to %d in UE_list %s, should never happen, Dumping UE list\n", - nodeP, - (ul_flag == 0) ? "DL" : "UL"); - dump_ue_list(listP, - ul_flag); + LOG_E(MAC, "%s(): could not find previous to %d in UE_list\n", __func__, nodeP); + dump_ue_list(listP); return -1; } -//------------------------------------------------------------------------------ -void -swap_UEs(UE_list_t *listP, - int nodeiP, - int nodejP, - int ul_flag) -//------------------------------------------------------------------------------ -{ - int prev_i, prev_j, next_i, next_j; - LOG_T(MAC, "Swapping UE %d,%d\n", - nodeiP, - nodejP); - dump_ue_list(listP, - ul_flag); - prev_i = prev(listP, - nodeiP, - ul_flag); - prev_j = prev(listP, - nodejP, - ul_flag); - AssertFatal((prev_i >= 0) && (prev_j >= 0), "swap_UEs: problem"); - - if (ul_flag == 0) { - next_i = listP->next[nodeiP]; - next_j = listP->next[nodejP]; - } else { - next_i = listP->next_ul[nodeiP]; - next_j = listP->next_ul[nodejP]; - } - - LOG_T(MAC, "[%s] next_i %d, next_i, next_j %d, head %d \n", - (ul_flag == 0) ? "DL" : "UL", - next_i, - next_j, - listP->head); - - if (ul_flag == 0) { - if (next_i == nodejP) { // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ... - LOG_T(MAC, "Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n"); - listP->next[nodeiP] = next_j; - listP->next[nodejP] = nodeiP; - - if (nodeiP == listP->head) { // case i j n(j) - listP->head = nodejP; - } else { - listP->next[prev_i] = nodejP; - } - } else if (next_j == nodeiP) { // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ... - LOG_T(MAC, "Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n"); - listP->next[nodejP] = next_i; - listP->next[nodeiP] = nodejP; - - if (nodejP == listP->head) { // case j i n(i) - listP->head = nodeiP; - } else { - listP->next[prev_j] = nodeiP; - } - } else { // case ... p(i) i n(i) ... p(j) j n(j) ... - listP->next[nodejP] = next_i; - listP->next[nodeiP] = next_j; - - if (nodeiP == listP->head) { - LOG_T(MAC, "changing head to %d\n", - nodejP); - listP->head = nodejP; - listP->next[prev_j] = nodeiP; - } else if (nodejP == listP->head) { - LOG_D(MAC, "changing head to %d\n", - nodeiP); - listP->head = nodeiP; - listP->next[prev_i] = nodejP; - } else { - listP->next[prev_i] = nodejP; - listP->next[prev_j] = nodeiP; - } - } - } else { // ul_flag - if (next_i == nodejP) { // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ... - LOG_T(MAC, "[UL] Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n"); - listP->next_ul[nodeiP] = next_j; - listP->next_ul[nodejP] = nodeiP; - - if (nodeiP == listP->head_ul) { // case i j n(j) - listP->head_ul = nodejP; - } else { - listP->next_ul[prev_i] = nodejP; - } - } else if (next_j == nodeiP) { // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ... - LOG_T(MAC, "[UL]Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n"); - listP->next_ul[nodejP] = next_i; - listP->next_ul[nodeiP] = nodejP; - - if (nodejP == listP->head_ul) { // case j i n(i) - listP->head_ul = nodeiP; - } else { - listP->next_ul[prev_j] = nodeiP; - } - } else { // case ... p(i) i n(i) ... p(j) j n(j) ... - listP->next_ul[nodejP] = next_i; - listP->next_ul[nodeiP] = next_j; - - if (nodeiP == listP->head_ul) { - LOG_T(MAC, "[UL]changing head to %d\n", - nodejP); - listP->head_ul = nodejP; - listP->next_ul[prev_j] = nodeiP; - } else if (nodejP == listP->head_ul) { - LOG_T(MAC, "[UL]changing head to %d\n", - nodeiP); - listP->head_ul = nodeiP; - listP->next_ul[prev_i] = nodejP; - } else { - listP->next_ul[prev_i] = nodejP; - listP->next_ul[prev_j] = nodeiP; - } - } - } - - LOG_T(MAC, "After swap\n"); - dump_ue_list(listP, - ul_flag); - return; -} - // This has to be updated to include BSR information //------------------------------------------------------------------------------ uint8_t @@ -2523,8 +2360,8 @@ UE_is_to_be_scheduled(module_id_t module_idP, uint8_t UE_id) //------------------------------------------------------------------------------ { - UE_TEMPLATE *UE_template = &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id]; - UE_sched_ctrl_t *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id]; + UE_TEMPLATE *UE_template = &RC.mac[module_idP]->UE_info.UE_template[CC_id][UE_id]; + UE_sched_ctrl_t *UE_sched_ctl = &RC.mac[module_idP]->UE_info.UE_sched_ctrl[UE_id]; int rrc_status; // do not schedule UE if UL is not working @@ -2566,7 +2403,7 @@ get_tmode(module_id_t module_idP, { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - struct LTE_PhysicalConfigDedicated *physicalConfigDedicated = eNB->UE_list.UE_template[CC_idP][UE_idP].physicalConfigDedicated; + struct LTE_PhysicalConfigDedicated *physicalConfigDedicated = eNB->UE_info.UE_template[CC_idP][UE_idP].physicalConfigDedicated; if (physicalConfigDedicated == NULL) { // RRCConnectionSetup not received by UE yet AssertFatal(cc->p_eNB <= 2, "p_eNB is %d, should be <2\n", @@ -2776,19 +2613,21 @@ get_min_rb_unit(module_id_t module_id, int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth); switch (N_RB_DL) { - case 6: // 1.4 MHz + case 6: // 1.4MHz min_rb_unit = 1; break; - case 25: // 5HMz + case 15: // 3MHz + case 25: // 5MHz min_rb_unit = 2; break; - case 50: // 10HMz + case 50: // 10MHz min_rb_unit = 3; break; - case 100: // 20HMz + case 75: // 15MHz + case 100: // 20MHz min_rb_unit = 4; break; @@ -2809,7 +2648,7 @@ uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, - uint8_t *rballoc) + const uint8_t *rballoc) //------------------------------------------------------------------------------ { int check = 0; //check1=0,check2=0; @@ -3482,7 +3321,7 @@ try_again: if (fCCE == -1) { if (DL_req->number_pdcch_ofdm_symbols == max_symbol) { - LOG_I(MAC, "subframe %d: Dropping Allocation for RNTI %x\n", + LOG_D(MAC, "subframe %d: Dropping Allocation for RNTI %x\n", subframeP, dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti); @@ -3671,6 +3510,121 @@ CCE_allocation_infeasible(int module_idP, return res; } +int CCE_try_allocate_dlsch(int module_id, + int CC_id, + int subframe, + int UE_id, + uint8_t dl_cqi) { + const rnti_t rnti = RC.mac[module_id]->UE_info.UE_template[CC_id][UE_id].rnti; + nfapi_dl_config_request_body_t *DL_req = &RC.mac[module_id]->DL_req[CC_id].dl_config_request_body; + + if (DL_req->number_pdu >= MAX_NUM_DL_PDU) { + LOG_W(MAC, "Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", subframe, rnti); + return -1; + } + + int aggregation = 2; + const uint8_t tm = get_tmode(module_id, CC_id, UE_id); + switch (tm) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_id, CC_id), + dl_cqi, + format1); + break; + + case 3: + aggregation = get_aggregation(get_bw_index(module_id, CC_id), + dl_cqi, + format2A); + break; + + default: + AssertFatal(0, "Unsupported transmission mode %d\n", tm); + break; + } + + nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu]; + memset(dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation; + DL_req->number_pdu++; + LOG_D(MAC, "Subframe %d: Checking CCE feasibility format 1: (%x,%d) \n", + subframe, rnti, aggregation); + + if (allocate_CCEs(module_id, CC_id, 0, subframe, 0) < 0) { + DL_req->number_pdu--; + return -1; + } + + DL_req->number_dci++; + nfapi_dl_config_request_pdu_t *dl_dlsch_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu]; + dl_dlsch_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_dlsch_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG; + dl_dlsch_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = rnti; + DL_req->number_pdu++; + + return DL_req->number_pdu - 2; +} + +int CCE_try_allocate_ulsch(int module_id, + int CC_id, + int subframe, + int UE_id, + uint8_t dl_cqi) { + const rnti_t rnti = RC.mac[module_id]->UE_info.UE_template[CC_id][UE_id].rnti; + nfapi_hi_dci0_request_body_t *HI_DCI0_req = &RC.mac[module_id]->HI_DCI0_req[CC_id][subframe].hi_dci0_request_body; + + if (HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi >= MAX_NUM_HI_DCI0_PDU) { + LOG_W(MAC, "Subframe %d: FAPI UL structure is full, skip scheduling UE %d\n", subframe, rnti); + return -1; + } + + int aggregation = 2; + const uint8_t tm = get_tmode(module_id, CC_id, UE_id); + switch (tm) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_id, CC_id), + dl_cqi, + format1); + break; + + case 3: + aggregation = get_aggregation(get_bw_index(module_id, CC_id), + dl_cqi, + format2A); + break; + + default: + AssertFatal(0, "Unsupported transmission mode %d\n", tm); + break; + } + + const int idx = HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[idx]; + memset(hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + HI_DCI0_req->number_of_dci++; + LOG_D(MAC, "%s() sf %d: Checking CCE feasibility format 2: RNTI %04x, agg %d\n", + __func__, subframe, rnti, aggregation); + + if (allocate_CCEs(module_id, CC_id, 0, subframe, 0) < 0) { + HI_DCI0_req->number_of_dci--; + return -1; + } + + return idx; +} + //------------------------------------------------------------------------------ void get_retransmission_timing(LTE_TDD_Config_t *tdd_Config, @@ -3931,15 +3885,15 @@ extract_harq(module_id_t mod_idP, //------------------------------------------------------------------------------ { eNB_MAC_INST *eNB = RC.mac[mod_idP]; - UE_list_t *UE_list = &eNB->UE_list; - UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_info_t *UE_info = &eNB->UE_info; + UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; rnti_t rnti = UE_RNTI(mod_idP, UE_id); COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd; nfapi_harq_indication_tdd_rel13_t *harq_indication_tdd; uint16_t num_ack_nak; - int numCC = UE_list->numactiveCCs[UE_id]; - int pCCid = UE_list->pCC_id[UE_id]; + int numCC = UE_info->numactiveCCs[UE_id]; + int pCCid = UE_info->pCC_id[UE_id]; int spatial_bundling = 0; int tmode[5]; int i, j, m; @@ -3947,7 +3901,7 @@ extract_harq(module_id_t mod_idP, sub_frame_t subframe_tx; int frame_tx; uint8_t harq_pid; - LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated; + LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_info->UE_template[pCCid][UE_id].physicalConfigDedicated; if (physicalConfigDedicated != NULL && physicalConfigDedicated->pucch_ConfigDedicated != NULL && physicalConfigDedicated->ext7 != NULL && physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13 != NULL && @@ -4081,7 +4035,7 @@ extract_harq(module_id_t mod_idP, sched_ctl->round[CC_idP][harq_pid]); // use 1 HARQ proces of BL/CE UE for now - if (UE_list->UE_template[pCCid][UE_id].rach_resource_type > 0) harq_pid = 0; + if (UE_info->UE_template[pCCid][UE_id].rach_resource_type > 0) harq_pid = 0; switch (harq_indication_fdd->mode) { case 0: // Format 1a/b (10.1.2.1) @@ -4567,18 +4521,18 @@ extract_pucch_csi(module_id_t mod_idP, uint8_t length) //------------------------------------------------------------------------------ { - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; + UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; int no_pmi; uint8_t Ltab[6] = { 0, 2, 4, 4, 4, 4 }; uint8_t Jtab[6] = { 0, 2, 2, 3, 4, 4 }; int feedback_cnt; - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", + AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", UE_id); - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n", + AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n", UE_id); - struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic; + struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic; AssertFatal(cqi_ReportPeriodic != NULL, "cqi_ReportPeriodic is null for UE %d\n", UE_id); // determine feedback mode @@ -4678,9 +4632,9 @@ extract_pusch_csi(module_id_t mod_idP, uint8_t length) //------------------------------------------------------------------------------ { - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; - UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; int Ntab[6] = { 0, 4, 7, 9, 10, 13 }; int Ntab_uesel[6] = { 0, 8, 13, 17, 19, 25 }; int Ltab_uesel[6] = { 0, 6, 9, 13, 15, 18 }; @@ -4689,12 +4643,12 @@ extract_pusch_csi(module_id_t mod_idP, int i; uint64_t p = *(uint64_t *) pdu; int curbyte, curbit; - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", + AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", UE_id); - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n", + AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n", UE_id); LTE_CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic - = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic; + = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic; AssertFatal(cqi_ReportModeAperiodic != NULL, "cqi_ReportModeAperiodic is null for UE %d\n", UE_id); int N = Ntab[cc->mib->message.dl_Bandwidth]; @@ -4964,14 +4918,14 @@ cqi_indication(module_id_t mod_idP, //------------------------------------------------------------------------------ { int UE_id = find_UE_id(mod_idP, rntiP); - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; if (UE_id == -1) { LOG_W(MAC, "cqi_indication: UE %x not found\n", rntiP); return; } - UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; if (UE_id >= 0) { LOG_D(MAC,"%s() UE_id:%d channel:%d cqi:%d\n", @@ -5037,11 +4991,11 @@ SR_indication(module_id_t mod_idP, T_INT(subframeP), T_INT(rntiP)); int UE_id = find_UE_id(mod_idP, rntiP); - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; UE_sched_ctrl_t *UE_scheduling_ctrl = NULL; if (UE_id != -1) { - UE_scheduling_ctrl = &(UE_list->UE_sched_ctrl[UE_id]); + UE_scheduling_ctrl = &(UE_info->UE_sched_ctrl[UE_id]); if ((UE_scheduling_ctrl->cdrx_configured == TRUE) && (UE_scheduling_ctrl->dci0_ongoing_timer > 0) && @@ -5065,8 +5019,8 @@ SR_indication(module_id_t mod_idP, cc_idP); } - UE_list->UE_template[cc_idP][UE_id].ul_SR = 1; - UE_list->UE_template[cc_idP][UE_id].ul_active = TRUE; + UE_info->UE_template[cc_idP][UE_id].ul_SR = 1; + UE_info->UE_template[cc_idP][UE_id].ul_active = TRUE; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 0); } @@ -5093,7 +5047,7 @@ UL_failure_indication(module_id_t mod_idP, //------------------------------------------------------------------------------ { int UE_id = find_UE_id(mod_idP, rntiP); - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; if (UE_id != -1) { LOG_D(MAC, "[eNB %d][UE %d/%x] Frame %d subframeP %d Signaling UL Failure for UE %d on CC_id %d (timer %d)\n", @@ -5104,9 +5058,9 @@ UL_failure_indication(module_id_t mod_idP, subframeP, UE_id, cc_idP, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer); - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0) UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 1; + if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer == 0) UE_info->UE_sched_ctrl[UE_id].ul_failure_timer = 1; } else { // AssertFatal(0, "find_UE_id(%u,rnti %d) not found", enb_mod_idP, rntiP); // AssertError(0, 0, "Frame %d: find_UE_id(%u,rnti %d) not found\n", frameP, enb_mod_idP, rntiP); @@ -5169,8 +5123,8 @@ harq_indication(module_id_t mod_idP, return; } - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; + UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; // extract HARQ Information @@ -5201,51 +5155,3 @@ harq_indication(module_id_t mod_idP, return; } - -// Flexran Slicing functions -//------------------------------------------------------------------------------ -uint16_t -nb_rbs_allowed_slice(float rb_percentage, - int total_rbs) -//------------------------------------------------------------------------------ -{ - return (uint16_t) floor(rb_percentage * total_rbs); -} - -//------------------------------------------------------------------------------ -int -ue_dl_slice_membership(module_id_t mod_id, - int UE_id, - int slice_idx) -//------------------------------------------------------------------------------ -{ - eNB_MAC_INST *eNB = RC.mac[mod_id]; - - if (slice_idx < 0 || slice_idx >= eNB->slice_info.n_dl) { - LOG_W(MAC, "out of range slice index %d (slice ID %d)\n", - slice_idx, - eNB->slice_info.dl[slice_idx].id); - return 0; - } - - return eNB->UE_list.active[UE_id] == TRUE && eNB->UE_list.assoc_dl_slice_idx[UE_id] == slice_idx; -} - -//------------------------------------------------------------------------------ -int -ue_ul_slice_membership(module_id_t mod_id, - int UE_id, - int slice_idx) -//------------------------------------------------------------------------------ -{ - eNB_MAC_INST *eNB = RC.mac[mod_id]; - - if (slice_idx < 0 || slice_idx >= eNB->slice_info.n_ul) { - LOG_W(MAC, "out of range slice index %d (slice ID %d)\n", - slice_idx, - eNB->slice_info.dl[slice_idx].id); - return 0; - } - - return eNB->UE_list.active[UE_id] == TRUE && eNB->UE_list.assoc_ul_slice_idx[UE_id] == slice_idx; -} diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 7c3b536de2..3062e5c964 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -123,17 +123,15 @@ rx_sdu(const module_id_t enb_mod_idP, unsigned short rx_lengths[NB_RB_MAX]; uint8_t lcgid = 0; int lcgid_updated[4] = {0, 0, 0, 0}; - eNB_MAC_INST *mac = NULL; - UE_list_t *UE_list = NULL; + eNB_MAC_INST *mac = RC.mac[enb_mod_idP]; + UE_info_t *UE_info = &mac->UE_info; rrc_eNB_ue_context_t *ue_contextP = NULL; UE_sched_ctrl_t *UE_scheduling_control = NULL; UE_TEMPLATE *UE_template_ptr = NULL; /* Init */ current_rnti = rntiP; UE_id = find_UE_id(enb_mod_idP, current_rnti); - mac = RC.mac[enb_mod_idP]; harq_pid = subframe2harqpid(&mac->common_channels[CC_idP], frameP, subframeP); - UE_list = &mac->UE_list; memset(rx_ces, 0, MAX_NUM_CE * sizeof(unsigned char)); memset(rx_lcids, 0, NB_RB_MAX * sizeof(unsigned char)); memset(rx_lengths, 0, NB_RB_MAX * sizeof(unsigned short)); @@ -142,8 +140,8 @@ rx_sdu(const module_id_t enb_mod_idP, trace_pdu(DIRECTION_UPLINK, sduP, sdu_lenP, 0, WS_C_RNTI, current_rnti, frameP, subframeP, 0, 0); if (UE_id != -1) { - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template_ptr = &(UE_list->UE_template[CC_idP][UE_id]); + UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + UE_template_ptr = &UE_info->UE_template[CC_idP][UE_id]; LOG_D(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu round %d from PHY (rnti %x, UE_id %d) ul_cqi %d\n", enb_mod_idP, harq_pid, @@ -182,7 +180,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\n", + 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", enb_mod_idP, harq_pid, CC_idP, @@ -191,7 +189,8 @@ rx_sdu(const module_id_t enb_mod_idP, UE_scheduling_control->round_UL[CC_idP][harq_pid], ul_cqi, UE_id, - current_rnti); + current_rnti, + sdu_lenP); if (ul_cqi > 200) { // too high energy pattern UE_scheduling_control->pusch_snr[CC_idP] = ul_cqi; @@ -413,8 +412,8 @@ rx_sdu(const module_id_t enb_mod_idP, UE_id = old_UE_id; current_rnti = old_rnti; /* Clear timer */ - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template_ptr = &(UE_list->UE_template[CC_idP][UE_id]); + UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + UE_template_ptr = &UE_info->UE_template[CC_idP][UE_id]; UE_scheduling_control->uplane_inactivity_timer = 0; UE_scheduling_control->ul_inactivity_timer = 0; UE_scheduling_control->ul_failure_timer = 0; @@ -430,7 +429,7 @@ rx_sdu(const module_id_t enb_mod_idP, UE_template_ptr->ul_SR = 1; UE_scheduling_control->crnti_reconfigurationcomplete_flag = 1; - UE_list->UE_template[UE_PCCID(enb_mod_idP, UE_id)][UE_id].configured = 1; + UE_info->UE_template[UE_PCCID(enb_mod_idP, UE_id)][UE_id].configured = 1; cancel_ra_proc(enb_mod_idP, CC_idP, frameP, @@ -480,8 +479,8 @@ rx_sdu(const module_id_t enb_mod_idP, ra->crnti_rrc_mui = rrc_eNB_mui-1; ra->crnti_harq_pid = -1; /* Clear timer */ - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template_ptr = &(UE_list->UE_template[CC_idP][UE_id]); + UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + UE_template_ptr = &UE_info->UE_template[CC_idP][UE_id]; UE_scheduling_control->uplane_inactivity_timer = 0; UE_scheduling_control->ul_inactivity_timer = 0; UE_scheduling_control->ul_failure_timer = 0; @@ -532,7 +531,7 @@ rx_sdu(const module_id_t enb_mod_idP, UE_template_ptr->ul_buffer_info[LCGID3]; RC.eNB[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = (payload_ptr[0] & 0x3f); - if (UE_id == UE_list->head) { + if (UE_id == UE_info->list.head) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR, (payload_ptr[0] & 0x3f)); } @@ -689,8 +688,8 @@ rx_sdu(const module_id_t enb_mod_idP, frameP, ra->rnti, UE_id); - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template_ptr = &(UE_list->UE_template[CC_idP][UE_id]); + UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + UE_template_ptr = &UE_info->UE_template[CC_idP][UE_id]; } } else { LOG_D(MAC, "[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %ld\n", @@ -779,11 +778,11 @@ rx_sdu(const module_id_t enb_mod_idP, enb_mod_idP, CC_idP, frameP, rx_lengths[i], UE_id, rx_lcids[i]); mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL); //(unsigned int*)crc_status); - UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1; - UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; if (mac_eNB_get_rrc_status(enb_mod_idP, current_rnti) < RRC_RECONFIGURED) { - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; } } @@ -840,8 +839,8 @@ rx_sdu(const module_id_t enb_mod_idP, if ((rx_lengths[i] < SCH_PAYLOAD_SIZE_MAX) && (rx_lengths[i] > 0)) { // MAX SIZE OF transport block mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL); - UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1; - UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; /* Clear uplane_inactivity_timer */ UE_scheduling_control->uplane_inactivity_timer = 0; /* Reset RRC inactivity timer after uplane activity */ @@ -856,7 +855,7 @@ rx_sdu(const module_id_t enb_mod_idP, current_rnti); } } else { /* rx_length[i] Max size */ - UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_errors_rx += 1; LOG_E(MAC, "[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d ", enb_mod_idP, CC_idP, @@ -921,12 +920,12 @@ rx_sdu(const module_id_t enb_mod_idP, /* NN--> FK: we could either check the payload, or use a phy helper to detect a false msg3 */ if ((num_sdu == 0) && (num_ce == 0)) { if (UE_id != -1) - UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx += 1; } else { if (UE_id != -1) { - UE_list->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx = sdu_lenP; - UE_list->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx += sdu_lenP; - UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx = sdu_lenP; + UE_info->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx += sdu_lenP; + UE_info->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx += 1; } } @@ -1101,16 +1100,12 @@ schedule_ulsch(module_id_t module_idP, sub_frame_t subframeP) //----------------------------------------------------------------------------- { - uint16_t first_rb[NFAPI_CC_MAX]; eNB_MAC_INST *mac = NULL; - slice_info_t *sli = NULL; COMMON_channels_t *cc = NULL; int sched_subframe; int sched_frame; /* Init */ mac = RC.mac[module_idP]; - sli = &(mac->slice_info); - memset(first_rb, 0, NFAPI_CC_MAX * sizeof(uint16_t)); start_meas(&(mac->schedule_ulsch)); sched_subframe = (subframeP + 4) % 10; sched_frame = frameP; @@ -1217,60 +1212,53 @@ schedule_ulsch(module_id_t module_idP, /* Note: RC.nb_mac_CC[module_idP] should be lower than or equal to NFAPI_CC_MAX */ for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++, cc++) { - first_rb[CC_id] = (emtc_active[CC_id] == 1) ? 7 : 1; - RA_t *ra_ptr = cc->ra; - - /* From Louis-Adrien to François: - * The comment bloc below is to configure with a command line. - * I took it from the equivalent part in the fairRR scheduler (around line 2578 in eNB_scheduler_fairRR.c). - * As said in the meeting, it seems to work only for small TBS. - * The cause of false RA still present with this fix is to investigate. - * - * Note: in the get_prach_prb_offset() function below, the last argument is frameP in eNB_scheduler_fairRR.c - * I think it should be sched_frame instead. This parameter has only impacts in case TDD and preamble format 4. - * To confirm. - */ - /* - int start_rb = 0; - int nb_rb = 6; - LTE_DL_FRAME_PARMS *frame_parms = &(RC.eNB[module_idP][CC_id]->frame_parms); - - if (is_prach_subframe(frame_parms, sched_frame, sched_subframe) == 1) { - start_rb = get_prach_prb_offset(frame_parms, - frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset, - 0, // tdd_mapindex - sched_frame); // Nf - - first_rb[CC_id] = start_rb + nb_rb; + LTE_DL_FRAME_PARMS *frame_parms = &RC.eNB[module_idP][CC_id]->frame_parms; + if (is_prach_subframe(frame_parms, sched_frame, sched_subframe)) { + int start_rb = get_prach_prb_offset( + frame_parms, + frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, + frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset, + 0, // tdd_mapindex + sched_frame); // Nf + for (int i = 0; i < 6; i++) + cc[CC_id].vrb_map_UL[start_rb + i] = 1; } - */ - /* - * Check if RA (Msg3) is active in this subframeP, if so skip the PRB used for Msg3 - * Msg3 is using 1 PRB so we need to increase first_rb accordingly - * Not sure about the break (can there be more than 1 active RA procedure per CC_id and per subframe?) + /* HACK: let's remove the PUCCH from available RBs + * we suppose PUCCH size is: + * - for 25 RBs: 1 RB (top and bottom of ressource grid) + * - for 50: 2 RBs + * - for 100: 3 RBs + * This is totally arbitrary and might even be wrong. */ - for (int ra_index = 0; ra_index < NB_RA_PROC_MAX; ra_index++, ra_ptr++) { - if ((ra_ptr->state == WAITMSG3) && (ra_ptr->Msg3_subframe == sched_subframe)) { - if (first_rb[CC_id] < ra_ptr->msg3_first_rb + ra_ptr->msg3_nb_rb) { - first_rb[CC_id] = ra_ptr->msg3_first_rb + ra_ptr->msg3_nb_rb; - } + switch (to_prb(cc[CC_id].ul_Bandwidth)) { + case 25: + cc[CC_id].vrb_map_UL[0] = 1; + cc[CC_id].vrb_map_UL[24] = 1; + break; - /* Louis-Adrien: I couldn't find an interdiction of multiple Msg3 scheduling - * on the same time resources. Also the performance improvement of breaking is low, - * since we will loop until the end, most of the time. - * I'm letting the break as a reminder, in case of misunderstanding the spec. - */ - // break; - } + case 50: + cc[CC_id].vrb_map_UL[0] = 1; + cc[CC_id].vrb_map_UL[1] = 1; + cc[CC_id].vrb_map_UL[48] = 1; + cc[CC_id].vrb_map_UL[49] = 1; + break; + + case 100: + cc[CC_id].vrb_map_UL[0] = 1; + cc[CC_id].vrb_map_UL[1] = 1; + cc[CC_id].vrb_map_UL[2] = 1; + cc[CC_id].vrb_map_UL[97] = 1; + cc[CC_id].vrb_map_UL[98] = 1; + cc[CC_id].vrb_map_UL[99] = 1; + break; + + default: + LOG_E(MAC, "RBs setting not handled. Todo.\n"); + exit(1); } - } - /* Run each enabled slice-specific schedulers one by one */ - for (int i = 0; i < sli->n_ul; i++) { - /* By default the scheduler is schedule_ulsch_rnti (see below) */ - sli->ul[i].sched_cb(module_idP, i, frameP, subframeP, sched_subframe, first_rb); + schedule_ulsch_rnti(module_idP, CC_id, frameP, subframeP, sched_subframe); } stop_meas(&mac->schedule_ulsch); @@ -1282,48 +1270,20 @@ schedule_ulsch(module_id_t module_idP, */ void schedule_ulsch_rnti(module_id_t module_idP, - int slice_idx, + int CC_id, frame_t frameP, sub_frame_t subframeP, - unsigned char sched_subframeP, - uint16_t *first_rb) -//----------------------------------------------------------------------------- -{ - rnti_t rnti = -1; - uint8_t aggregation = 2; - uint8_t round_index = 0; - uint8_t harq_pid = 0; - uint8_t status = 0; - uint8_t rb_table_index = -1; - uint8_t dlsch_flag = 0; - uint16_t ul_req_index = 0; - uint32_t cqi_req = 0; - uint32_t cshift = 0; - uint32_t ndi = 0; - uint32_t tpc = 0; - int32_t snr = 0; - int32_t target_snr = 0; - int32_t framex10psubframe = 0; + unsigned char sched_subframeP) { + /* TODO: does this need to be static? */ static int32_t tpc_accumulated = 0; - int sched_frame = 0; - int CC_id = 0; - eNB_MAC_INST *mac = NULL; - COMMON_channels_t *cc = NULL; - UE_list_t *UE_list = NULL; - slice_info_t *sli = NULL; - UE_TEMPLATE *UE_template_ptr = NULL; - UE_sched_ctrl_t *UE_sched_ctrl_ptr = NULL; - int rvidx_tab[4] = {0, 2, 3, 1}; - int first_rb_slice[NFAPI_CC_MAX]; - int n_rb_ul_tab[NFAPI_CC_MAX]; - /* Init */ - mac = RC.mac[module_idP]; - cc = mac->common_channels; - UE_list = &(mac->UE_list); - sli = &(mac->slice_info); - memset(first_rb_slice, 0, NFAPI_CC_MAX * sizeof(int)); - memset(n_rb_ul_tab, 0, NFAPI_CC_MAX * sizeof(int)); - sched_frame = frameP; + /* values from 0 to 7 can be used for mapping the cyclic shift + * (36.211 , Table 5.5.2.1.1-1) */ + const uint32_t cshift = 0; + eNB_MAC_INST *mac = RC.mac[module_idP]; + COMMON_channels_t *cc = mac->common_channels; + UE_info_t *UE_info = &mac->UE_info; + + int sched_frame = frameP; if (sched_subframeP < subframeP) { sched_frame++; @@ -1339,63 +1299,23 @@ schedule_ulsch_rnti(module_id_t module_idP, nfapi_ul_config_ulsch_harq_information *ulsch_harq_information; hi_dci0_req->sfn_sf = (frameP << 4) + subframeP; - /* Note: RC.nb_mac_CC[module_idP] should be lower than or equal to NFAPI_CC_MAX */ - for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - n_rb_ul_tab[CC_id] = to_prb(cc[CC_id].ul_Bandwidth); // return total number of PRB - - /* HACK: let's remove the PUCCH from available RBs - * we suppose PUCCH size is: - * - for 25 RBs: 1 RB (top and bottom of ressource grid) - * - for 50: 2 RBs - * - for 100: 3 RBs - * This is totally arbitrary and might even be wrong. - * We suppose 'first_rb[]' has been correctly populated by the caller, - * so we only remove the top part of the resource grid. - */ - switch (n_rb_ul_tab[CC_id]) { - case 25: - n_rb_ul_tab[CC_id] -= 1; - break; - - case 50: - n_rb_ul_tab[CC_id] -= 2; - break; - - case 100: - n_rb_ul_tab[CC_id] -= 3; - break; - - default: - LOG_E(MAC, "RBs setting not handled. Todo.\n"); - exit(1); - } - - UE_list->first_rb_offset[CC_id][slice_idx] = cmin(n_rb_ul_tab[CC_id], sli->ul[slice_idx].first_rb); - } - /* * ULSCH preprocessor: set UE_template-> * pre_allocated_nb_rb_ul[slice_idx] * pre_assigned_mcs_ul * pre_allocated_rb_table_index_ul */ - ulsch_scheduler_pre_processor(module_idP, slice_idx, frameP, subframeP, sched_frame, sched_subframeP, first_rb); + ulsch_scheduler_pre_processor(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP); - for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - first_rb_slice[CC_id] = first_rb[CC_id] + UE_list->first_rb_offset[CC_id][slice_idx]; - } - - // loop over all active UEs until end of function - for (int UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - if (!ue_ul_slice_membership(module_idP, UE_id, slice_idx)) { + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0) continue; - } - - if (UE_list->UE_template[UE_PCCID(module_idP, UE_id)][UE_id].rach_resource_type > 0) continue; // don't schedule if Msg5 is not received yet - if (UE_list->UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured == FALSE) { - LOG_D(MAC, "[eNB %d] frame %d, subframe %d, UE %d: not configured, skipping UE scheduling \n", + if (UE_info->UE_template[CC_id][UE_id].configured == FALSE) { + LOG_D(MAC, + "[eNB %d] frame %d, subframe %d, UE %d: not configured, skipping " + "UE scheduling \n", module_idP, frameP, subframeP, @@ -1403,10 +1323,11 @@ schedule_ulsch_rnti(module_id_t module_idP, continue; } - rnti = UE_RNTI(module_idP, UE_id); + const rnti_t rnti = UE_RNTI(module_idP, UE_id); if (rnti == NOT_A_RNTI) { - LOG_W(MAC, "[eNB %d] frame %d, subframe %d, UE %d: no RNTI \n", + LOG_W(MAC, + "[eNB %d] frame %d, subframe %d, UE %d: no RNTI \n", module_idP, frameP, subframeP, @@ -1414,485 +1335,509 @@ schedule_ulsch_rnti(module_id_t module_idP, continue; } - // loop over all active UL CC_ids for this UE until end of function - for (int n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - /* This is the actual CC_id in the list */ - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template_ptr = &(UE_list->UE_template[CC_id][UE_id]); - UE_sched_ctrl_ptr = &(UE_list->UE_sched_ctrl[UE_id]); - harq_pid = subframe2harqpid(&cc[CC_id], sched_frame, sched_subframeP); - round_index = UE_sched_ctrl_ptr->round_UL[CC_id][harq_pid]; - AssertFatal(round_index < 8, "round %d > 7 for UE %d/%x\n", - round_index, - UE_id, - rnti); - LOG_D(MAC, "[eNB %d] frame %d subframe %d (sched_frame %d, sched_subframe %d), Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n", + UE_TEMPLATE *UE_template_ptr = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl_t *UE_sched_ctrl_ptr = &UE_info->UE_sched_ctrl[UE_id]; + const uint8_t harq_pid = subframe2harqpid(&cc[CC_id], sched_frame, sched_subframeP); + uint8_t round_index = UE_sched_ctrl_ptr->round_UL[CC_id][harq_pid]; + AssertFatal(round_index < 8, + "round %d > 7 for UE %d/%x\n", + round_index, + UE_id, + rnti); + + /* Seems unused, only for debug */ + RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP * 10) + subframeP] = + UE_template_ptr->estimated_ul_buffer; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO, + UE_template_ptr->estimated_ul_buffer); + + if (UE_template_ptr->pre_allocated_nb_rb_ul < 1) + continue; + + int dci_ul_pdu_idx = UE_template_ptr->pre_dci_ul_pdu_idx; + if (dci_ul_pdu_idx < 0) { + dci_ul_pdu_idx = CCE_try_allocate_ulsch( + module_idP, CC_id, subframeP, UE_id, UE_sched_ctrl_ptr->dl_cqi[CC_id]); + if (dci_ul_pdu_idx < 0) { + LOG_W(MAC ,"%4d.%d: Dropping UL Allocation for RNTI 0x%04x/UE %d\n", + frameP, subframeP, rnti, UE_id); + continue; + } + } + + /* verify it is the right UE */ + hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[dci_ul_pdu_idx]; + if (hi_dci0_pdu->pdu_type != NFAPI_HI_DCI0_DCI_PDU_TYPE + || hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti != rnti) { + LOG_E(MAC, "illegal hi_dci0_pdu_list index %d for UE %d/RNTI %04x\n", + dci_ul_pdu_idx, + UE_id, + rnti); + continue; + } + + LOG_D(MAC, + "[eNB %d][PUSCH %d] %d.%d Scheduling UE %d/%x in " + "round %d (SR %d, UL_inactivity timer %d, UL_failure timer " + "%d, cqi_req_timer %d)\n", + module_idP, + harq_pid, + frameP, + subframeP, + UE_id, + rnti, + round_index, + UE_template_ptr->ul_SR, + UE_sched_ctrl_ptr->ul_inactivity_timer, + UE_sched_ctrl_ptr->ul_failure_timer, + UE_sched_ctrl_ptr->cqi_req_timer); + + /* Reset the scheduling request */ + UE_template_ptr->ul_SR = 0; + const uint8_t status = mac_eNB_get_rrc_status(module_idP, rnti); + + /* Power control */ + /* + * Compute the expected ULSCH RX snr (for the stats) + * This is the normalized RX snr and this should be constant (regardless + * of mcs) Is not in dBm, unit from nfapi, converting to dBm + */ + const int32_t snr = (5 * UE_sched_ctrl_ptr->pusch_snr[CC_id] - 640) / 10; + const int32_t target_snr = mac->puSch10xSnr / 10; + + /* + * This assumes accumulated tpc + * Make sure that we are only sending a tpc update once a frame, otherwise + * the control loop will freak out + */ + const int32_t fx10psf = (UE_template_ptr->pusch_tpc_tx_frame * 10) + + UE_template_ptr->pusch_tpc_tx_subframe; + uint32_t tpc = 1; + if (((fx10psf + 10) <= (frameP * 10 + subframeP)) // normal case + || ((fx10psf > (frameP * 10 + subframeP)) + && (((10240 - fx10psf + frameP * 10 + subframeP) >= 10)))) { // frame wrap-around + UE_template_ptr->pusch_tpc_tx_frame = frameP; + UE_template_ptr->pusch_tpc_tx_subframe = subframeP; + + if (snr > target_snr + 4) { + tpc = 0; // -1 + tpc_accumulated--; + } else if (snr < target_snr - 4) { + tpc = 2; // +1 + tpc_accumulated++; + } + } + if (tpc != 1) { + LOG_D(MAC, + "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, " + "tpc %d, accumulated %d, snr/target snr %d/%d\n", module_idP, frameP, subframeP, - sched_frame, - sched_subframeP, harq_pid, + tpc, + tpc_accumulated, + snr, + target_snr); + } + + /* New transmission */ + if (round_index == 0) { + /* Handle the aperiodic CQI report */ + uint32_t cqi_req = 0; + LOG_D(MAC, + "RRC Connection status %d, cqi_timer %d\n", + status, + UE_sched_ctrl_ptr->cqi_req_timer); + + if (status >= RRC_CONNECTED && UE_sched_ctrl_ptr->cqi_req_timer > 30) { + if (UE_sched_ctrl_ptr->cqi_received == 0) { + cqi_req = 1; + LOG_D(MAC, + "Setting CQI_REQ (timer %d)\n", + UE_sched_ctrl_ptr->cqi_req_timer); + + /* TDD: to be safe, do not ask CQI in special + * Subframes:36.213/7.2.3 CQI definition */ + if (cc[CC_id].tdd_Config) { + switch (cc[CC_id].tdd_Config->subframeAssignment) { + case 1: + if (subframeP == 1 || subframeP == 6) + cqi_req = 0; + break; + + case 3: + if (subframeP == 1) + cqi_req = 0; + break; + + default: + LOG_E(MAC, " TDD config not supported\n"); + break; + } + } + + if (cqi_req == 1) + UE_sched_ctrl_ptr->cqi_req_flag |= 1 << sched_subframeP; + } else { + LOG_D(MAC, "Clearing CQI request timer\n"); + UE_sched_ctrl_ptr->cqi_req_flag = 0; + UE_sched_ctrl_ptr->cqi_received = 0; + UE_sched_ctrl_ptr->cqi_req_timer = 0; + } + } + + const uint8_t ndi = 1 - UE_template_ptr->oldNDI_UL[harq_pid]; // NDI: new data indicator + const uint8_t mcs = UE_template_ptr->pre_assigned_mcs_ul; + UE_template_ptr->oldNDI_UL[harq_pid] = ndi; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_template_ptr->mcs_UL[harq_pid] = mcs; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = mcs; + + /* CDRX */ + if (UE_sched_ctrl_ptr->cdrx_configured) { + // reset drx inactivity timer when new transmission + UE_sched_ctrl_ptr->drx_inactivity_timer = 1; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( + VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, + (unsigned long)UE_sched_ctrl_ptr->drx_inactivity_timer); + // when set the UE_template_ptr->ul_SR cannot be set to 1, + // see definition for more information + UE_sched_ctrl_ptr->dci0_ongoing_timer = 1; + } + + uint8_t rb_table_index = UE_template_ptr->pre_allocated_rb_table_index_ul; + + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = mcs; + + while (rb_table[rb_table_index] > 45 && rb_table_index > 0) + rb_table_index--; + + UE_template_ptr->TBS_UL[harq_pid] = get_TBS_UL(mcs, rb_table[rb_table_index]); + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template_ptr->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].total_ulsch_TBS += UE_template_ptr->TBS_UL[harq_pid]; + T(T_ENB_MAC_UE_UL_SCHEDULE, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(mcs), + T_INT(rb_table[rb_table_index]), + T_INT(UE_template_ptr->TBS_UL[harq_pid]), + T_INT(ndi)); + /* Store information for possible retransmission */ + UE_template_ptr->nb_rb_ul[harq_pid] = rb_table[rb_table_index]; + UE_template_ptr->first_rb_ul[harq_pid] = UE_template_ptr->pre_first_nb_rb_ul; + UE_template_ptr->cqi_req[harq_pid] = cqi_req; + UE_sched_ctrl_ptr->ul_scheduled |= (1 << harq_pid); + + if (UE_id == UE_info->list.head) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( + VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED, + UE_sched_ctrl_ptr->ul_scheduled); + } + + /* Adjust scheduled UL bytes by TBS, wait for UL sdus to do final update */ + LOG_D(MAC, + "[eNB %d] CC_id %d UE %d/%x : adjusting scheduled_ul_bytes, old " + "%d, TBS %d\n", + module_idP, + CC_id, UE_id, rnti, - CC_id, - aggregation, - n_rb_ul_tab[CC_id]); - /* Seems unused, only for debug */ - RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP * 10) + subframeP] = UE_template_ptr->estimated_ul_buffer; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO, UE_template_ptr->estimated_ul_buffer); + UE_template_ptr->scheduled_ul_bytes, + UE_template_ptr->TBS_UL[harq_pid]); + UE_template_ptr->scheduled_ul_bytes += UE_template_ptr->TBS_UL[harq_pid]; + LOG_D(MAC, + "scheduled_ul_bytes, new %d\n", + UE_template_ptr->scheduled_ul_bytes); + /* Cyclic shift for DM-RS */ + /* Save it for a potential retransmission */ + UE_template_ptr->cshift[harq_pid] = cshift; + /* Setting DCI0 NFAPI struct */ + hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[dci_ul_pdu_idx]; + hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu); + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = UE_template_ptr->pre_first_nb_rb_ul; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = + rb_table[rb_table_index]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = mcs; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = ndi; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = + UE_template_ptr->DAI_ul[sched_subframeP]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid; + hi_dci0_req_body->sfnsf = + sfnsf_add_subframe(sched_frame, sched_subframeP, 0); + hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG; + hi_dci0_req->sfn_sf = frameP << 4 | subframeP; + hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST; + LOG_D(MAC, + "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE " + "%d/%x, ulsch_frame %d, ulsch_subframe %d\n", + harq_pid, + frameP, + subframeP, + UE_id, + rnti, + sched_frame, + sched_subframeP); + uint16_t ul_req_index = 0; + uint8_t dlsch_flag = 0; - /* - * If there is information on BSR of DCCH, DTCH or if there is UL_SR, - * or if there is a packet to retransmit, or we want to schedule a periodic feedback - */ - if (UE_is_to_be_scheduled(module_idP, CC_id, UE_id) > 0 || round_index > 0) { - LOG_D(MAC, "[eNB %d][PUSCH %d] Frame %d subframe %d Scheduling UE %d/%x in round %d(SR %d,UL_inactivity timer %d,UL_failure timer %d,cqi_req_timer %d)\n", - module_idP, - harq_pid, + for (ul_req_index = 0; ul_req_index < ul_req_tmp_body->number_of_pdus; ul_req_index++) { + if (ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) { + dlsch_flag = 1; + LOG_D(MAC, + "Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI " + "HARQ to ULSCH HARQ(first)\n", + frameP, + subframeP, + rnti, + ul_req_index); + break; + } + } + + /* Add UL_config PDUs */ + fill_nfapi_ulsch_config_request_rel8( + &ul_req_tmp_body->ul_config_pdu_list[ul_req_index], + cqi_req, + cc, + UE_template_ptr->physicalConfigDedicated, + get_tmode(module_idP, CC_id, UE_id), + mac->ul_handle, + rnti, + UE_template_ptr->pre_first_nb_rb_ul, // resource_block_start + rb_table[rb_table_index], // number_of_resource_blocks + mcs, + cshift, // cyclic_shift_2_for_drms + 0, // frequency_hopping_enabled_flag + 0, // frequency_hopping_bits + ndi, // new_data_indication + 0, // redundancy_version + harq_pid, // harq_process_number + 0, // ul_tx_mode + 0, // current_tx_nb + 0, // n_srs + get_TBS_UL(mcs, rb_table[rb_table_index])); + + /* This is a BL/CE UE allocation */ + if (UE_template_ptr->rach_resource_type > 0) { + fill_nfapi_ulsch_config_request_emtc( + &ul_req_tmp_body->ul_config_pdu_list[ul_req_index], + UE_template_ptr->rach_resource_type > 2 ? 2 : 1, + 1, // total_number_of_repetitions + 1, // repetition_number + (frameP * 10) + subframeP); + } + + if (dlsch_flag == 1) { + if (cqi_req == 1) { + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; + ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = rb_table[rb_table_index]; + } else { + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; + ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = rb_table[rb_table_index]; + } + + fill_nfapi_ulsch_harq_information(module_idP, CC_id, rnti, ulsch_harq_information, subframeP); + } else { + ul_req_tmp_body->number_of_pdus++; + } + + ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST; + ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; + mac->ul_handle++; + ul_req_tmp->sfn_sf = sched_frame << 4 | sched_subframeP; + add_ue_ulsch_info(module_idP, CC_id, UE_id, subframeP, S_UL_SCHEDULED); + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for " + "next UE_id %d, format 0\n", + module_idP, + CC_id, + frameP, + subframeP, + UE_id); + LOG_D( + MAC, + "[PUSCH %d] SFN/SF:%04d%d UL_CFG:SFN/SF:%04d%d CQI:%d for UE %d/%x\n", + harq_pid, + frameP, + subframeP, + sched_frame, + sched_subframeP, + cqi_req, + UE_id, + rnti); + } else { // round_index > 0 => retransmission + uint8_t mcs_rv = 0; + const int rvidx_tab[4] = {0, 2, 3, 1}; + uint8_t round_UL = UE_sched_ctrl_ptr->round_UL[CC_id][harq_pid]; + if (rvidx_tab[round_UL & 3] == 1) { + mcs_rv = 29; + } else if (rvidx_tab[round_UL & 3] == 2) { + mcs_rv = 30; + } else if (rvidx_tab[round_UL & 3] == 3) { + mcs_rv = 31; + } + + const uint16_t first_rb = UE_template_ptr->pre_first_nb_rb_ul; + const uint8_t nb_rb = UE_template_ptr->pre_allocated_nb_rb_ul; + if (first_rb != UE_template_ptr->first_rb_ul[harq_pid] + || nb_rb != UE_template_ptr->nb_rb_ul[harq_pid]) + LOG_D(MAC, + "%4d.%d UE %4x retx: change freq allocation to %d RBs start %d (from %d RBs start %d)\n", frameP, subframeP, - UE_id, rnti, - round_index, - UE_template_ptr->ul_SR, - UE_sched_ctrl_ptr->ul_inactivity_timer, - UE_sched_ctrl_ptr->ul_failure_timer, - UE_sched_ctrl_ptr->cqi_req_timer); - /* Reset the scheduling request */ - UE_template_ptr->ul_SR = 0; - status = mac_eNB_get_rrc_status(module_idP, rnti); + nb_rb, + first_rb, + UE_template_ptr->nb_rb_ul[harq_pid], + UE_template_ptr->first_rb_ul[harq_pid]); + UE_template_ptr->first_rb_ul[harq_pid] = first_rb; + UE_template_ptr->nb_rb_ul[harq_pid] = nb_rb; - /* New transmission */ - if (round_index == 0) { - /* Be sure that there are some free RBs */ - if (first_rb_slice[CC_id] >= n_rb_ul_tab[CC_id]) { - LOG_W(MAC, "[eNB %d] frame %d, subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n", - module_idP, - frameP, - subframeP, - UE_id, - rnti, - CC_id); - continue; - } + T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(mcs_rv), + T_INT(first_rb), + T_INT(nb_rb), + T_INT(round_index)); + /* Add UL_config PDUs */ + LOG_D(MAC, + "[PUSCH %d] %4d.%d: Adding UL CONFIG.Request for UE " + "%d/%x, ulsch_frame %d, ulsch_subframe %d\n", + harq_pid, + frameP, + subframeP, + UE_id, + rnti, + sched_frame, + sched_subframeP); - /* Should format_flag be 2 in CCE_allocation_infeasible??? */ - /* This test seems to be way too long, can we provide an optimization? */ - if (CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP, aggregation, rnti)) { - LOG_W(MAC, "[eNB %d] frame %d, subframe %d, UE %d/%x CC %d: not enough CCE\n", - module_idP, - frameP, - subframeP, - UE_id, - rnti, - CC_id); - continue; - } + hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[dci_ul_pdu_idx]; + hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu); + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = nb_rb; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = mcs_rv; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = UE_template_ptr->oldNDI_UL[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = UE_template_ptr->cqi_req[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template_ptr->DAI_ul[sched_subframeP]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid; - /* Handle the aperiodic CQI report */ - cqi_req = 0; - LOG_D(MAC,"RRC Conenction status %d, cqi_timer %d\n",status,UE_sched_ctrl_ptr->cqi_req_timer); - - if (status >= RRC_CONNECTED && UE_sched_ctrl_ptr->cqi_req_timer > 30) { - if (UE_sched_ctrl_ptr->cqi_received == 0) { - cqi_req = 1; - LOG_D(MAC, - "Setting CQI_REQ (timer %d)\n", - UE_sched_ctrl_ptr->cqi_req_timer); - - /* TDD: to be safe, do not ask CQI in special - * Subframes:36.213/7.2.3 CQI definition */ - if (cc[CC_id].tdd_Config) { - switch (cc[CC_id].tdd_Config->subframeAssignment) { - case 1: - if (subframeP == 1 || subframeP == 6) - cqi_req = 0; - break; - - case 3: - if (subframeP == 1) - cqi_req = 0; - break; - - default: - LOG_E(MAC, " TDD config not supported\n"); - break; - } - } - - if (cqi_req == 1) { - UE_sched_ctrl_ptr->cqi_req_flag |= 1 << sched_subframeP; - } - } else { - LOG_D(MAC,"Clearing CQI request timer\n"); - UE_sched_ctrl_ptr->cqi_req_flag = 0; - UE_sched_ctrl_ptr->cqi_received = 0; - UE_sched_ctrl_ptr->cqi_req_timer = 0; - } - } - - /* Power control */ - /* - * Compute the expected ULSCH RX snr (for the stats) - * This is the normalized RX snr and this should be constant (regardless of mcs) - * Is not in dBm, unit from nfapi, converting to dBm - */ - snr = (5 * UE_sched_ctrl_ptr->pusch_snr[CC_id] - 640) / 10; - target_snr = mac->puSch10xSnr / 10; - /* - * This assumes accumulated tpc - * Make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out - */ - framex10psubframe = (UE_template_ptr->pusch_tpc_tx_frame * 10) + UE_template_ptr->pusch_tpc_tx_subframe; - - if (((framex10psubframe + 10) <= (frameP * 10 + subframeP)) || // normal case - ((framex10psubframe > (frameP * 10 + subframeP)) && (((10240 - framex10psubframe + frameP * 10 + subframeP) >= 10)))) { //frame wrap-around - UE_template_ptr->pusch_tpc_tx_frame = frameP; - UE_template_ptr->pusch_tpc_tx_subframe = subframeP; - - if (snr > target_snr + 4) { - tpc = 0; // -1 - tpc_accumulated--; - } else if (snr < target_snr - 4) { - tpc = 2; // +1 - tpc_accumulated++; - } else { - tpc = 1; // 0 - } - } else { - tpc = 1; // 0 - } - - if (tpc != 1) { - LOG_D(MAC, "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n", - module_idP, - frameP, - subframeP, - harq_pid, - tpc, - tpc_accumulated, - snr, - target_snr); - } - - ndi = 1 - UE_template_ptr->oldNDI_UL[harq_pid]; // NDI: new data indicator - UE_template_ptr->oldNDI_UL[harq_pid] = ndi; - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; - UE_template_ptr->mcs_UL[harq_pid] = cmin(UE_template_ptr->pre_assigned_mcs_ul, sli->ul[slice_idx].maxmcs); - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1= UE_template_ptr->mcs_UL[harq_pid]; - - /* CDRX */ - if (UE_sched_ctrl_ptr->cdrx_configured) { - UE_sched_ctrl_ptr->drx_inactivity_timer = 1; // reset drx inactivity timer when new transmission - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) UE_sched_ctrl_ptr->drx_inactivity_timer); - UE_sched_ctrl_ptr->dci0_ongoing_timer = 1; // when set the UE_template_ptr->ul_SR cannot be set to 1, - // see definition for more information - } - - if (UE_template_ptr->pre_allocated_rb_table_index_ul >= 0) { - rb_table_index = UE_template_ptr->pre_allocated_rb_table_index_ul; - } else { - UE_template_ptr->mcs_UL[harq_pid] = 10; - rb_table_index = 5; // for PHR - } - - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template_ptr->mcs_UL[harq_pid]; - - while (((rb_table[rb_table_index] > (n_rb_ul_tab[CC_id] - first_rb_slice[CC_id])) || - (rb_table[rb_table_index] > 45)) && (rb_table_index > 0)) { - rb_table_index--; - } - - UE_template_ptr->TBS_UL[harq_pid] = get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], rb_table[rb_table_index]); - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index]; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template_ptr->TBS_UL[harq_pid]; - UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_TBS += UE_template_ptr->TBS_UL[harq_pid]; - T(T_ENB_MAC_UE_UL_SCHEDULE, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(UE_template_ptr->mcs_UL[harq_pid]), - T_INT(first_rb_slice[CC_id]), - T_INT(rb_table[rb_table_index]), - T_INT(UE_template_ptr->TBS_UL[harq_pid]), - T_INT(ndi)); - /* Store information for possible retransmission */ - UE_template_ptr->nb_rb_ul[harq_pid] = rb_table[rb_table_index]; - UE_template_ptr->first_rb_ul[harq_pid] = first_rb_slice[CC_id]; - UE_template_ptr->cqi_req[harq_pid] = cqi_req; - UE_sched_ctrl_ptr->ul_scheduled |= (1 << harq_pid); - - if (UE_id == UE_list->head) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED, UE_sched_ctrl_ptr->ul_scheduled); - } - - /* Adjust scheduled UL bytes by TBS, wait for UL sdus to do final update */ - LOG_D(MAC, "[eNB %d] CC_id %d UE %d/%x : adjusting scheduled_ul_bytes, old %d, TBS %d\n", - module_idP, - CC_id, - UE_id, + uint16_t ul_req_index = 0; + uint8_t dlsch_flag = 0; + uint32_t cqi_req = UE_template_ptr->cqi_req[harq_pid]; + for (ul_req_index = 0; ul_req_index < ul_req_tmp_body->number_of_pdus; ul_req_index++) { + if (ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) { + dlsch_flag = 1; + LOG_D(MAC, + "Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI " + "HARQ to ULSCH HARQ(first)\n", + frameP, + subframeP, rnti, - UE_template_ptr->scheduled_ul_bytes, - UE_template_ptr->TBS_UL[harq_pid]); - UE_template_ptr->scheduled_ul_bytes += UE_template_ptr->TBS_UL[harq_pid]; - LOG_D(MAC, "scheduled_ul_bytes, new %d\n", - UE_template_ptr->scheduled_ul_bytes); - /* Cyclic shift for DM-RS */ - cshift = 0; // values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1) - /* Save it for a potential retransmission */ - UE_template_ptr->cshift[harq_pid] = cshift; - /* Setting DCI0 NFAPI struct */ - hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi]; - memset((void *) hi_dci0_pdu, 0,sizeof(nfapi_hi_dci0_request_pdu_t)); - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; - hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu); - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb_slice[CC_id]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template_ptr->mcs_UL[harq_pid]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = ndi; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template_ptr->DAI_ul[sched_subframeP]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid; - hi_dci0_req_body->number_of_dci++; - hi_dci0_req_body->sfnsf = sfnsf_add_subframe(sched_frame, sched_subframeP, 0); - hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG; - hi_dci0_req->sfn_sf = frameP << 4 | subframeP; - hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST; - LOG_D(MAC, "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", - harq_pid, - frameP, - subframeP, - UE_id, - rnti, - sched_frame, - sched_subframeP); - ul_req_index = 0; - dlsch_flag = 0; + ul_req_index); + break; + } + } - for(ul_req_index = 0; ul_req_index < ul_req_tmp_body->number_of_pdus; ul_req_index++) { - if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) { - dlsch_flag = 1; - LOG_D(MAC, "Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n", - frameP, - subframeP, - rnti, - ul_req_index); - break; - } - } + fill_nfapi_ulsch_config_request_rel8( + &ul_req_tmp_body->ul_config_pdu_list[ul_req_index], + cqi_req, + cc, + UE_template_ptr->physicalConfigDedicated, + get_tmode(module_idP, CC_id, UE_id), + mac->ul_handle, + rnti, + first_rb, // resource_block_start + nb_rb, // number_of_resource_blocks + mcs_rv, + cshift, // cyclic_shift_2_for_drms + 0, // frequency_hopping_enabled_flag + 0, // frequency_hopping_bits + UE_template_ptr->oldNDI_UL[harq_pid], // new_data_indication + rvidx_tab[round_index & 3], // redundancy_version + harq_pid, // harq_process_number + 0, // ul_tx_mode + 0, // current_tx_nb + 0, // n_srs + UE_template_ptr->TBS_UL[harq_pid]); - /* Add UL_config PDUs */ - fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], - cqi_req, - cc, - UE_template_ptr->physicalConfigDedicated, - get_tmode(module_idP, CC_id, UE_id), - mac->ul_handle, - rnti, - first_rb_slice[CC_id], // resource_block_start - rb_table[rb_table_index], // number_of_resource_blocks - UE_template_ptr->mcs_UL[harq_pid], - cshift, // cyclic_shift_2_for_drms - 0, // frequency_hopping_enabled_flag - 0, // frequency_hopping_bits - ndi, // new_data_indication - 0, // redundancy_version - harq_pid, // harq_process_number - 0, // ul_tx_mode - 0, // current_tx_nb - 0, // n_srs - get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], rb_table[rb_table_index])); + /* This is a BL/CE UE allocation */ + if (UE_template_ptr->rach_resource_type > 0) { + fill_nfapi_ulsch_config_request_emtc( + &ul_req_tmp_body->ul_config_pdu_list[ul_req_index], + UE_template_ptr->rach_resource_type > 2 ? 2 : 1, + 1, // total_number_of_repetitions + 1, // repetition_number + (frameP * 10) + subframeP); + } - /* This is a BL/CE UE allocation */ - if (UE_template_ptr->rach_resource_type > 0) { - fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], - UE_template_ptr->rach_resource_type > 2 ? 2 : 1, - 1, // total_number_of_repetitions - 1, // repetition_number - (frameP * 10) + subframeP); - } + if (dlsch_flag == 1) { + if (cqi_req == 1) { + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; + ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = UE_template_ptr->nb_rb_ul[harq_pid]; + } else { + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; + ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = UE_template_ptr->nb_rb_ul[harq_pid]; + } - if (dlsch_flag == 1) { - if (cqi_req == 1) { - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; - ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = - NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = - rb_table[rb_table_index]; - } else { - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; - ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = - NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = rb_table[rb_table_index]; - } + fill_nfapi_ulsch_harq_information(module_idP, CC_id, rnti, ulsch_harq_information, subframeP); + } else { + ul_req_tmp_body->number_of_pdus++; + } - fill_nfapi_ulsch_harq_information(module_idP, CC_id,rnti, ulsch_harq_information,subframeP); - } else { - ul_req_tmp_body->number_of_pdus++; - } - - ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST; - ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; - mac->ul_handle++; - ul_req_tmp->sfn_sf = sched_frame << 4 | sched_subframeP; - add_ue_ulsch_info(module_idP, CC_id, UE_id, subframeP, S_UL_SCHEDULED); - LOG_D(MAC, "[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", - module_idP, - CC_id, - frameP, - subframeP, - UE_id); - LOG_D(MAC, "[PUSCH %d] SFN/SF:%04d%d UL_CFG:SFN/SF:%04d%d CQI:%d for UE %d/%x\n", - harq_pid, - frameP, - subframeP, - sched_frame, - sched_subframeP, - cqi_req, - UE_id, - rnti); - /* Increment first rb for next UE allocation */ - first_rb_slice[CC_id] += rb_table[rb_table_index]; - } else { // round_index > 0 => retransmission - T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(UE_template_ptr->mcs_UL[harq_pid]), - T_INT(UE_template_ptr->first_rb_ul[harq_pid]), - T_INT(UE_template_ptr->nb_rb_ul[harq_pid]), - T_INT(round_index)); - /* Add UL_config PDUs */ - LOG_D(MAC, "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", - harq_pid, - frameP, - subframeP, - UE_id, - rnti, - sched_frame, - sched_subframeP); - ul_req_index = 0; - dlsch_flag = 0; - cqi_req = UE_template_ptr->cqi_req[harq_pid]; - - for(ul_req_index = 0; ul_req_index < ul_req_tmp_body->number_of_pdus; ul_req_index++) { - if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) { - dlsch_flag = 1; - LOG_D(MAC, "Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n", - frameP, - subframeP, - rnti, - ul_req_index); - break; - } - } - - fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], - cqi_req, - cc, - UE_template_ptr->physicalConfigDedicated, - get_tmode(module_idP, CC_id, UE_id), - mac->ul_handle, - rnti, - UE_template_ptr->first_rb_ul[harq_pid], // resource_block_start - UE_template_ptr->nb_rb_ul[harq_pid], // number_of_resource_blocks - UE_template_ptr->mcs_UL[harq_pid], - cshift, // cyclic_shift_2_for_drms - 0, // frequency_hopping_enabled_flag - 0, // frequency_hopping_bits - UE_template_ptr->oldNDI_UL[harq_pid], // new_data_indication - rvidx_tab[round_index & 3], // redundancy_version - harq_pid, // harq_process_number - 0, // ul_tx_mode - 0, // current_tx_nb - 0, // n_srs - UE_template_ptr->TBS_UL[harq_pid]); - - /* This is a BL/CE UE allocation */ - if (UE_template_ptr->rach_resource_type > 0) { - fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], - UE_template_ptr->rach_resource_type > 2 ? 2 : 1, - 1, // total_number_of_repetitions - 1, // repetition_number - (frameP * 10) + subframeP); - } - - if(dlsch_flag == 1) { - if(cqi_req == 1) { - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; - ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag= - NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = - UE_template_ptr->nb_rb_ul[harq_pid]; - } else { - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; - ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = - NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = - UE_template_ptr->nb_rb_ul[harq_pid]; - } - - fill_nfapi_ulsch_harq_information(module_idP, CC_id,rnti, ulsch_harq_information, subframeP); - } else { - ul_req_tmp_body->number_of_pdus++; - } - - mac->ul_handle++; - ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; - ul_req_tmp->sfn_sf = sched_frame<<4|sched_subframeP; - ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST; - LOG_D(MAC, "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d cqi_req %d\n", - harq_pid, - frameP, - subframeP, - UE_id, - rnti, - sched_frame, - sched_subframeP, - cqi_req); - - /* HACK: RBs used by retransmission have to be reserved. - * The current mechanism uses the notion of 'first_rb', so - * we skip all RBs below the ones retransmitted. This is - * not correct. Imagine only RB 23 is retransmitted, then all - * RBs < 23 will be marked unusable for new transmissions (case where round == 0). - * Note also that this code works only if the preprocessor orders - * UEs with retransmission with higher priority than UEs with new - * transmission. - * All this should be cleaned up properly. - */ - if (first_rb_slice[CC_id] < UE_template_ptr->first_rb_ul[harq_pid] + UE_template_ptr->nb_rb_ul[harq_pid]) - first_rb_slice[CC_id] = UE_template_ptr->first_rb_ul[harq_pid] + UE_template_ptr->nb_rb_ul[harq_pid]; - } // end of round > 0 - } // UE_is_to_be_scheduled - } // loop over all active CC_ids - } // loop over UE_ids + mac->ul_handle++; + ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; + ul_req_tmp->sfn_sf = sched_frame << 4 | sched_subframeP; + ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST; + LOG_D(MAC, + "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE " + "%d/%x, ulsch_frame %d, ulsch_subframe %d cqi_req %d\n", + harq_pid, + frameP, + subframeP, + UE_id, + rnti, + sched_frame, + sched_subframeP, + cqi_req); + } // end of round > 0 + } // loop over UE_ids } @@ -1926,7 +1871,7 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, eNB_MAC_INST *eNB = RC.mac[module_idP]; eNB_RRC_INST *rrc = RC.rrc[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &(eNB->UE_list); + UE_info_t *UE_info = &eNB->UE_info; UE_TEMPLATE *UE_template = NULL; UE_sched_ctrl_t *UE_sched_ctrl = NULL; uint8_t Total_Num_Rep_ULSCH,pusch_maxNumRepetitionCEmodeA_r13; @@ -1944,8 +1889,8 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, nfapi_ul_config_request_pdu_t *ul_config_pdu_Rep; /* Loop over all active UEs */ - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - UE_template = &(UE_list->UE_template[UE_PCCID(module_idP, UE_id)][UE_id]); + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_template = &UE_info->UE_template[UE_PCCID(module_idP, UE_id)][UE_id]; /* LTE-M device */ if (UE_template->rach_resource_type == 0) { @@ -1974,12 +1919,12 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, } /* Loop over all active UL CC_ids for this UE */ - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { /* This is the actual CC_id in the list */ - CC_id = UE_list->ordered_ULCCids[n][UE_id]; + CC_id = UE_info->ordered_ULCCids[n][UE_id]; N_RB_UL = to_prb(cc[CC_id].ul_Bandwidth); - UE_template = &(UE_list->UE_template[CC_id][UE_id]); - UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = 0; round_UL = UE_sched_ctrl->round_UL[CC_id][harq_pid]; AssertFatal(round_UL < 8,"round_UL %d > 7 for UE %d/%x\n", @@ -2027,6 +1972,12 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, UE_sched_ctrl->cqi_req_timer); /* Reset the scheduling request */ emtc_active[CC_id] = 1; + cc[CC_id].vrb_map_UL[1] = 1; + cc[CC_id].vrb_map_UL[2] = 1; + cc[CC_id].vrb_map_UL[3] = 1; + cc[CC_id].vrb_map_UL[4] = 1; + cc[CC_id].vrb_map_UL[5] = 1; + cc[CC_id].vrb_map_UL[6] = 1; UE_template->ul_SR = 0; status = mac_eNB_get_rrc_status(module_idP,rnti); cqi_req = 0; @@ -2074,12 +2025,12 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, UE_template->oldNDI_UL[harq_pid] = ndi; UE_template->mcs_UL[harq_pid] = 4; UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid], 6); - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = 4; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template->mcs_UL[harq_pid]; - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += 6; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = 4; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template->mcs_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += 6; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template->TBS_UL[harq_pid]; T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), @@ -2096,7 +2047,7 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, UE_template->nb_rb_ul[harq_pid] = 6; UE_sched_ctrl->ul_scheduled |= (1 << harq_pid); - if (UE_id == UE_list->head) { + if (UE_id == UE_info->list.head) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED, UE_sched_ctrl->ul_scheduled); } diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index ac9819cfe2..329e262c82 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -824,11 +824,16 @@ typedef struct { uint16_t cshift[8]; // num_max_harq /// Number of Allocated RBs by the ulsch preprocessor - uint8_t pre_allocated_nb_rb_ul[MAX_NUM_SLICES]; + uint8_t pre_allocated_nb_rb_ul; + /// Start of Allocated RBs by the USLCH preprocessor + uint8_t pre_first_nb_rb_ul; /// index of Allocated RBs by the ulsch preprocessor int8_t pre_allocated_rb_table_index_ul; + /// index of allocated HI_DCI0 + int pre_dci_ul_pdu_idx; + /// total allocated RBs int8_t total_allocated_rbs; @@ -852,10 +857,10 @@ typedef struct { // Logical channel info for link with RLC - /// LCGID mapping + /// LCGID mapping (UL) long lcgidmap[11]; - ///UE logical channel priority + ///UE logical channel priority (UL) long lcgidpriority[11]; /// phr information @@ -913,31 +918,12 @@ typedef struct { /*! \brief scheduling control information set through an API (not used)*/ typedef struct { - ///UL transmission bandwidth in RBs - uint8_t ul_bandwidth[MAX_NUM_LCID]; - ///DL transmission bandwidth in RBs - uint8_t dl_bandwidth[MAX_NUM_LCID]; - - //To do GBR bearer - uint8_t min_ul_bandwidth[MAX_NUM_LCID]; - - uint8_t min_dl_bandwidth[MAX_NUM_LCID]; - - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateDL; - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateUL; - ///CQI scheduling interval in subframes. - uint16_t cqiSchedInterval; - ///Contention resolution timer used during random access - uint8_t mac_ContentionResolutionTimer; - - uint16_t max_rbs_allowed_slice[NFAPI_CC_MAX][MAX_NUM_SLICES]; - uint16_t max_rbs_allowed_slice_uplink[NFAPI_CC_MAX][MAX_NUM_SLICES]; - - uint8_t max_mcs[MAX_NUM_LCID]; - - uint16_t priority[MAX_NUM_LCID]; + /// number of active DL LCs + uint8_t dl_lc_num; + /// order in which DLSCH scheduler should allocate LCs + uint8_t dl_lc_ids[MAX_NUM_LCID]; + /// number of bytes to schedule for each LC + uint32_t dl_lc_bytes[MAX_NUM_LCID]; // resource scheduling information @@ -950,6 +936,7 @@ typedef struct { uint8_t dl_pow_off[NFAPI_CC_MAX]; uint16_t pre_nb_available_rbs[NFAPI_CC_MAX]; unsigned char rballoc_sub_UE[NFAPI_CC_MAX][N_RBG_MAX]; + int pre_dci_dl_pdu_idx; uint16_t ta_timer; int16_t ta_update; uint16_t ul_consecutive_errors; @@ -1130,7 +1117,15 @@ typedef struct { uint8_t sb_size; uint8_t nb_active_sb; } SBMAP_CONF; -/*! \brief UE list used by eNB to order UEs/CC for scheduling*/ + +/*! \brief UE_list_t is a "list" of users within UE_info_t. Especial useful in + * the scheduler and to keep "classes" of users. */ +typedef struct { + int head; + int next[MAX_MOBILES_PER_ENB]; +} UE_list_t; + +/*! \brief UE info used by eNB to order UEs/CC for scheduling*/ typedef struct { DLSCH_PDU DLSCH_pdu[NFAPI_CC_MAX][2][MAX_MOBILES_PER_ENB]; @@ -1152,21 +1147,13 @@ typedef struct { eNB_UE_STATS eNB_UE_stats[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; /// scheduling control info UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_ENB]; - int next[MAX_MOBILES_PER_ENB]; - int head; - int next_ul[MAX_MOBILES_PER_ENB]; - int head_ul; - int avail; + UE_list_t list; int num_UEs; boolean_t active[MAX_MOBILES_PER_ENB]; /// Sorting criteria for the UE list in the MAC preprocessor uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM]; - uint16_t first_rb_offset[NFAPI_CC_MAX][MAX_NUM_SLICES]; - - int assoc_dl_slice_idx[MAX_MOBILES_PER_ENB]; - int assoc_ul_slice_idx[MAX_MOBILES_PER_ENB]; -} UE_list_t; +} UE_info_t; /*! \brief deleting control information*/ typedef struct { @@ -1184,20 +1171,6 @@ typedef struct { int tail_freelist; ///the tail position of the delete list } UE_free_list_t; -/// Structure for saving the output of each pre_processor instance -typedef struct { - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]; - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]; - - uint32_t bytes_lcid[MAX_MOBILES_PER_ENB][MAX_NUM_LCID]; - uint32_t wb_pmi[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint8_t mcs[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - -} pre_processor_results_t; - /** * slice specific scheduler for the DL */ @@ -1289,12 +1262,18 @@ typedef struct { int n_ul; slice_sched_conf_ul_t ul[MAX_NUM_SLICES]; - pre_processor_results_t pre_processor_results[MAX_NUM_SLICES]; - /// common rb allocation list between slices uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]; } slice_info_t; +/** + * describes contiguous RBs + */ +typedef struct { + int start; + int length; +} contig_rbs_t; + /*! \brief eNB common channels */ typedef struct { int physCellId; @@ -1414,7 +1393,7 @@ typedef struct eNB_MAC_INST_s { nfapi_ue_release_request_t UE_release_req; /// UL handle uint32_t ul_handle; - UE_list_t UE_list; + UE_info_t UE_info; /// slice-related configuration slice_info_t slice_info; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 476fb68584..2cb86c25af 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -122,15 +122,14 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP, /** \brief ULSCH Scheduling per RNTI @param Mod_id Instance ID of eNB -@param slice_idx Slice instance index for this eNB +@param CC_id The component carrier to schedule @param frame Frame index @param subframe Subframe number on which to act @param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup) */ -void schedule_ulsch_rnti(module_id_t module_idP, int slice_idx, frame_t frameP, +void schedule_ulsch_rnti(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframe, - unsigned char sched_subframe, - uint16_t *first_rb); + unsigned char sched_subframe); void schedule_ulsch_rnti_emtc(module_id_t module_idP, frame_t frameP, @@ -138,14 +137,6 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, unsigned char sched_subframeP, int *emtc_active); -/** \brief Second stage of DLSCH scheduling, after schedule_SI, schedule_RA and schedule_dlsch have been called. This routine first allocates random frequency assignments for SI and RA SDUs using distributed VRB allocations and adds the corresponding DCI SDU to the DCI buffer for PHY. It then loops over the UE specific DCIs previously allocated and fills in the remaining DCI fields related to frequency allocation. It assumes localized allocation of type 0 (DCI.rah=0). The allocation is done for tranmission modes 1,2,4. -@param Mod_id Instance of eNB -@param frame Frame index -@param subframe Index of subframe -@param mbsfn_flag Indicates that this subframe is for MCH/MCCH -*/ -void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag); - /** \brief UE specific DLSCH scheduling. Retrieves next ue to be schduled from round-robin scheduler and gets the appropriate harq_pid for the subframe from PHY. If the process is active and requires a retransmission, it schedules the retransmission with the same PRB count and MCS as the first transmission. Otherwise it consults RLC for DCCH/DTCH SDUs (status with maximum number of available PRBS), builds the MAC header (timing advance sent by default) and copies @param Mod_id Instance ID of eNB @param frame Frame index @@ -156,8 +147,10 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i void schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, int *mbsfn_flag); -void schedule_ue_spec(module_id_t module_idP, int slice_idxP, - frame_t frameP,sub_frame_t subframe, int *mbsfn_flag); +void schedule_ue_spec(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t subframe); void schedule_ue_spec_br(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); @@ -192,7 +185,7 @@ void add_msg3(module_id_t module_idP, int CC_id, RA_t *ra, frame_t frameP, //main.c -void init_UE_list(UE_list_t *UE_list); +void init_UE_info(UE_info_t *UE_info); void init_slice_info(slice_info_t *sli); @@ -231,73 +224,9 @@ void clear_nfapi_information(eNB_MAC_INST *eNB, int CC_idP, void dlsch_scheduler_pre_processor(module_id_t module_idP, - int slice_idxP, + int CC_id, frame_t frameP, - sub_frame_t subframe, - int *mbsfn_flag, - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); - -void dlsch_scheduler_pre_processor_reset(module_id_t module_idP, - int slice_idx, - frame_t frameP, - sub_frame_t subframeP, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX], - int *mbsfn_flag); - -void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id, - int slice_idx, - const uint8_t rbs_retx[NFAPI_CC_MAX]); - -void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, - int slice_idx, - frame_t frameP, - sub_frame_t subframeP, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]); - -void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, - int slice_idx, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); - -void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id, - int slice_idx, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); - -void slice_priority_sort(module_id_t Mod_id, int slice_list[MAX_NUM_SLICES]); - -void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, - int frameP, - sub_frame_t subframeP, - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); - -void dlsch_scheduler_qos_multiplexing(module_id_t Mod_id, - int frameP, - sub_frame_t subframeP); - -void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, - int UE_id, - uint8_t CC_id, - int N_RBG, - int min_rb_unit, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); + sub_frame_t subframe); /* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f. @@ -484,10 +413,23 @@ boolean_t CCE_allocation_infeasible(int module_idP, int common_flag, int subframe, int aggregation, int rnti); +/* tries to allocate a CCE. If it succeeds, reserves NFAPI DCI and DLSCH config */ +int CCE_try_allocate_dlsch(int module_id, + int CC_id, + int subframe, + int UE_id, + uint8_t dl_cqi); + +/* tries to allocate a CCE for UL. If it succeeds, reserves the NFAPI DCI */ +int CCE_try_allocate_ulsch(int module_id, + int CC_id, + int subframe, + int UE_id, + uint8_t dl_cqi); void set_ue_dai(sub_frame_t subframeP, int UE_id, - uint8_t CC_id, uint8_t tdd_config, UE_list_t *UE_list); + uint8_t CC_id, uint8_t tdd_config, UE_info_t *UE_info); uint8_t frame_subframe2_dl_harq_pid(LTE_TDD_Config_t *tdd_Config, int abs_frameP, sub_frame_t subframeP); /** \brief First stage of PCH Scheduling. Gets a PCH SDU from RRC if available and computes the MCS required to transport it as a function of the SDU length. It assumes a length less than or equal to 64 bytes (MCS 6, 3 PRBs). @@ -510,14 +452,6 @@ uint8_t UE_is_to_be_scheduled(module_id_t module_idP, int CC_id, module_id_t schedule_next_ulue(module_id_t module_idP, int UE_id, sub_frame_t subframe); -/** \brief Round-robin scheduler for DLSCH traffic. -@param Mod_id Instance ID for eNB -@param subframe Subframe number on which to act -@returns UE index that is to be scheduled if needed/room -*/ -int schedule_next_dlue(module_id_t module_idP, int CC_id, - sub_frame_t subframe); - /* \brief Allocates a set of PRBS for a particular UE. This is a simple function for the moment, later it should process frequency-domain CQI information and/or PMI information. Currently it just returns the first PRBS that are available in the subframe based on the number requested. @param UE_id Index of UE on which to act @param nb_rb Number of PRBs allocated to UE by scheduler @@ -721,13 +655,13 @@ int mac_init(void); int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid, uint8_t rach_resource_type); int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP); -void store_dlsch_buffer(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframeP); -void assign_rbs_required(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], int min_rb_unit[NFAPI_CC_MAX]); +void store_dlsch_buffer(module_id_t Mod_id, int CC_id, frame_t frameP, sub_frame_t subframeP); -void swap_UEs(UE_list_t *listP, int nodeiP, int nodejP, int ul_flag); -int prev(UE_list_t *listP, int nodeP, int ul_flag); -void dump_ue_list(UE_list_t *listP, int ul_flag); -int UE_num_active_CC(UE_list_t *listP, int ue_idP); +int prev(UE_list_t *listP, int nodeP); +void add_ue_list(UE_list_t *listP, int UE_id); +int remove_ue_list(UE_list_t *listP, int UE_id); +void dump_ue_list(UE_list_t *listP); +int UE_num_active_CC(UE_info_t *listP, int ue_idP); int UE_PCCID(module_id_t mod_idP, int ue_idP); rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP); @@ -739,20 +673,14 @@ void set_ul_DAI(int module_idP, int frameP, int subframeP); -void ulsch_scheduler_pre_processor(module_id_t module_idP, int slice_idx, int frameP, +void ulsch_scheduler_pre_processor(module_id_t module_idP, + int CC_id, + int frameP, sub_frame_t subframeP, int sched_frameP, - unsigned char sched_subframeP, - uint16_t *first_rb); -void store_ulsch_buffer(module_id_t module_idP, int frameP, - sub_frame_t subframeP); -void assign_max_mcs_min_rb(module_id_t module_idP, int slice_idx, int frameP, - sub_frame_t subframeP, uint16_t *first_rb); -void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, - UE_TEMPLATE *UE_template); + unsigned char sched_subframeP); int phy_stats_exist(module_id_t Mod_id, int rnti); -void sort_UEs(module_id_t Mod_idP, int slice_idx, int frameP, sub_frame_t subframeP); /*! \fn UE_L2_state_t ue_scheduler(const module_id_t module_idP,const frame_t frameP, const sub_frame_t subframe, const lte_subframe_t direction,const uint8_t eNB_index) \brief UE scheduler where all the ue background tasks are done. This function performs the following: 1) Trigger PDCP every 5ms 2) Call RRC for link status return to PHY3) Perform SR/BSR procedures for scheduling feedback 4) Perform PHR procedures. @@ -913,8 +841,7 @@ void add_common_dci(DCI_PDU *DCI_pdu, uint8_t ra_flag); */ -uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, - uint8_t *rballoc); +uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, const uint8_t *rballoc); void update_ul_dci(module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t dai, sub_frame_t subframe); @@ -1176,14 +1103,13 @@ void program_dlsch_acknak(module_id_t module_idP, int CC_idP, int UE_idP, frame_t frameP, sub_frame_t subframeP, uint8_t cce_idx); -void fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, - nfapi_dl_config_request_body_t *dl_req, +void fill_nfapi_dlsch_config(nfapi_dl_config_request_pdu_t *dl_config_pdu, uint16_t length, int16_t pdu_index, uint16_t rnti, uint8_t resource_allocation_type, uint8_t virtual_resource_block_assignment_flag, - uint16_t resource_block_coding, + uint32_t resource_block_coding, uint8_t modulation, uint8_t redundancy_version, uint8_t transport_blocks, @@ -1277,11 +1203,6 @@ void pre_scd_nb_rbs_required( module_id_t module_idP, uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX]); #endif -/* Slice related functions */ -uint16_t nb_rbs_allowed_slice(float rb_percentage, int total_rbs); -int ue_dl_slice_membership(module_id_t mod_id, int UE_id, int slice_idx); -int ue_ul_slice_membership(module_id_t mod_id, int UE_id, int slice_idx); - /* DRX Configuration */ /* Configure local DRX timers and thresholds in UE context, following the drx_configuration input */ void eNB_Config_Local_DRX(instance_t Mod_id, rrc_mac_drx_config_req_t *rrc_mac_drx_config_req); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index fe8980101d..1a88623a1f 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -43,26 +43,18 @@ extern RAN_CONTEXT_t RC; -void init_UE_list(UE_list_t *UE_list) +void init_UE_info(UE_info_t *UE_info) { int list_el; - UE_list->num_UEs = 0; - UE_list->head = -1; - UE_list->head_ul = -1; - UE_list->avail = 0; - for (list_el = 0; list_el < MAX_MOBILES_PER_ENB - 1; list_el++) { - UE_list->next[list_el] = list_el + 1; - UE_list->next_ul[list_el] = list_el + 1; - } - UE_list->next[list_el] = -1; - UE_list->next_ul[list_el] = -1; - memset(UE_list->DLSCH_pdu, 0, sizeof(UE_list->DLSCH_pdu)); - memset(UE_list->UE_template, 0, sizeof(UE_list->UE_template)); - memset(UE_list->eNB_UE_stats, 0, sizeof(UE_list->eNB_UE_stats)); - memset(UE_list->UE_sched_ctrl, 0, sizeof(UE_list->UE_sched_ctrl)); - memset(UE_list->active, 0, sizeof(UE_list->active)); - memset(UE_list->assoc_dl_slice_idx, 0, sizeof(UE_list->assoc_dl_slice_idx)); - memset(UE_list->assoc_ul_slice_idx, 0, sizeof(UE_list->assoc_ul_slice_idx)); + UE_info->num_UEs = 0; + UE_info->list.head = -1; + for (list_el = 0; list_el < MAX_MOBILES_PER_ENB; list_el++) + UE_info->list.next[list_el] = -1; + memset(UE_info->DLSCH_pdu, 0, sizeof(UE_info->DLSCH_pdu)); + memset(UE_info->UE_template, 0, sizeof(UE_info->UE_template)); + memset(UE_info->eNB_UE_stats, 0, sizeof(UE_info->eNB_UE_stats)); + memset(UE_info->UE_sched_ctrl, 0, sizeof(UE_info->UE_sched_ctrl)); + memset(UE_info->active, 0, sizeof(UE_info->active)); } void init_slice_info(slice_info_t *sli) @@ -137,7 +129,7 @@ void mac_top_init_eNB(void) mac[i]->if_inst = IF_Module_init(i); - init_UE_list(&mac[i]->UE_list); + init_UE_info(&mac[i]->UE_info); init_slice_info(&mac[i]->slice_info); } @@ -163,12 +155,12 @@ void mac_init_cell_params(int Mod_idP, int CC_idP) memset(&RC.mac[Mod_idP]->eNB_stats, 0, sizeof(eNB_STATS)); UE_template = - (UE_TEMPLATE *) & RC.mac[Mod_idP]->UE_list.UE_template[CC_idP][0]; + (UE_TEMPLATE *) & RC.mac[Mod_idP]->UE_info.UE_template[CC_idP][0]; for (j = 0; j < MAX_MOBILES_PER_ENB; j++) { UE_template[j].rnti = 0; // initiallize the eNB to UE statistics - memset(&RC.mac[Mod_idP]->UE_list.eNB_UE_stats[CC_idP][j], 0, + memset(&RC.mac[Mod_idP]->UE_info.eNB_UE_stats[CC_idP][j], 0, sizeof(eNB_UE_STATS)); } @@ -263,4 +255,4 @@ void *mac_enb_task(void *arg) } // end while return NULL; -} \ No newline at end of file +} diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index bd4e4de2a4..c4dd6b8419 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -50,109 +50,247 @@ extern RAN_CONTEXT_t RC; -#define DEBUG_eNB_SCHEDULER 1 +#define DEBUG_eNB_SCHEDULER #define DEBUG_HEADER_PARSING 1 -//#define DEBUG_PACKET_TRACE 1 -//#define ICIC 0 - -void -sort_ue_ul(module_id_t module_idP, - int slice_idx, - int sched_frameP, - sub_frame_t sched_subframeP, - rnti_t *rntiTable); - -/* this function checks that get_eNB_UE_stats returns - * a non-NULL pointer for all the active CCs of an UE - */ -/* -int phy_stats_exist(module_id_t Mod_id, int rnti) -{ - int CC_id; - int i; - int UE_id = find_UE_id(Mod_id, rnti); - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - if (UE_id == -1) { - LOG_W(MAC, "[eNB %d] UE %x not found, should be there (in phy_stats_exist)\n", - Mod_id, rnti); - return 0; +int next_ue_list_looped(UE_list_t* list, int UE_id) { + if (UE_id < 0) + return list->head; + return list->next[UE_id] < 0 ? list->head : list->next[UE_id]; +} + +int get_rbg_size_last(module_id_t Mod_id, int CC_id) { + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + const int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + if (N_RB_DL == 15 || N_RB_DL == 25 || N_RB_DL == 50 || N_RB_DL == 75) + return RBGsize - 1; + else + return RBGsize; +} + +int g_start_ue_dl = -1; +int round_robin_dl(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + UE_list_t *UE_list, + int max_num_ue, + int n_rbg_sched, + uint8_t *rbgalloc_mask) { + DevAssert(UE_list->head >= 0); + DevAssert(n_rbg_sched > 0); + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id); + int num_ue_req = 0; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + + int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request + memset(rb_required, 0, sizeof(rb_required)); + + int rbg = 0; + for (; !rbgalloc_mask[rbg]; rbg++) + ; /* fast-forward to first allowed RBG */ + + // Calculate the amount of RBs every UE wants to send. + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + // check whether there are HARQ retransmissions + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; + if (round != 8) { // retransmission: allocate + const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + if (nb_rb == 0) + continue; + int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; + // needs more RBGs than we can allocate + if (nb_rbg > n_rbg_sched) { + LOG_D(MAC, + "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", + UE_id, nb_rbg, n_rbg_sched); + continue; + } + // ensure that the number of RBs can be contained by the RBGs (!), i.e. + // if we allocate the last RBG this one should have the full RBGsize + if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched + && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { + LOG_D(MAC, + "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", + UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); + continue; + } + const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; // cannot allocate CCE + ue_ctrl->pre_dci_dl_pdu_idx = idx; + // retransmissions: directly allocate + n_rbg_sched -= nb_rbg; + ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; + for (; nb_rbg > 0; rbg++) { + if (!rbgalloc_mask[rbg]) + continue; + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + nb_rbg--; + } + LOG_D(MAC, + "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " + "round %d retx nb_rb %d pre_nb_available_rbs %d\n", + frame, subframe, n_rbg_sched, UE_id, round, + UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], + ue_ctrl->pre_nb_available_rbs[CC_id]); + /* if there are no more RBG to give, return */ + if (n_rbg_sched <= 0) + return 0; + max_num_ue--; + /* if there are no UEs that can be allocated anymore, return */ + if (max_num_ue == 0) + return n_rbg_sched; + for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } else { + const int dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = dlsch_mcs1; + rb_required[UE_id] = + find_nb_rb_DL(dlsch_mcs1, + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, + n_rbg_sched * RBGsize, + RBGsize); + if (rb_required[UE_id] > 0) + num_ue_req++; + LOG_D(MAC, + "%d/%d UE_id %d rb_required %d n_rbg_sched %d\n", + frame, + subframe, + UE_id, + rb_required[UE_id], + n_rbg_sched); + } } - if (UE_list->numactiveCCs[UE_id] == 0) { - LOG_W(MAC, "[eNB %d] UE %x has no active CC (in phy_stats_exist)\n", - Mod_id, rnti); - return 0; + + if (num_ue_req == 0) + return n_rbg_sched; // no UE has a transmission + + // after allocating retransmissions: build list of UE to allocate. + // if start_UE does not exist anymore (detach etc), start at first UE + if (g_start_ue_dl == -1) + g_start_ue_dl = UE_list->head; + int UE_id = g_start_ue_dl; + UE_list_t UE_sched; + int rb_required_total = 0; + int num_ue_sched = 0; + max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); + int *cur_UE = &UE_sched.head; + while (num_ue_sched < max_num_ue) { + while (rb_required[UE_id] == 0) + UE_id = next_ue_list_looped(UE_list, UE_id); + const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) { + LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id); + num_ue_req--; + max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); + UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate + continue; + } + UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; + *cur_UE = UE_id; + cur_UE = &UE_sched.next[UE_id]; + rb_required_total += rb_required[UE_id]; + num_ue_sched++; + UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate } - for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - if (mac_xface->get_eNB_UE_stats(Mod_id, CC_id, rnti) == NULL) - return 0; + *cur_UE = -1; + + /* for one UE after the next: allocate resources */ + for (int UE_id = UE_sched.head; UE_id >= 0; + UE_id = next_ue_list_looped(&UE_sched, UE_id)) { + if (rb_required[UE_id] <= 0) + continue; + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; + ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; + rb_required[UE_id] -= sRBG; + rb_required_total -= sRBG; + if (rb_required_total <= 0) + break; + n_rbg_sched--; + if (n_rbg_sched <= 0) + break; + for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } - return 1; + + /* if not all UEs could be allocated in this round */ + if (num_ue_req > max_num_ue) { + /* go to the first one we missed */ + for (int i = 0; i < max_num_ue; ++i) + g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); + } else { + /* else, just start with the next UE next time */ + g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); + } + + return n_rbg_sched; } -*/ // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer(module_id_t Mod_id, - int slice_idx, + int CC_id, frame_t frameP, sub_frame_t subframeP) { - int UE_id, lcid; - rnti_t rnti; - mac_rlc_status_resp_t rlc_status; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_TEMPLATE *UE_template; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id] != TRUE) - continue; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) - continue; - - UE_template = &UE_list->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id]; - // clear logical channel interface variables + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl_t *UE_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; UE_template->dl_buffer_total = 0; UE_template->dl_pdus_total = 0; - for (lcid = 0; lcid < MAX_NUM_LCID; ++lcid) { - UE_template->dl_buffer_info[lcid] = 0; - UE_template->dl_pdus_in_buffer[lcid] = 0; - UE_template->dl_buffer_head_sdu_creation_time[lcid] = 0; - UE_template->dl_buffer_head_sdu_remaining_size_to_send[lcid] = 0; - } - - rnti = UE_RNTI(Mod_id, UE_id); - - for (lcid = 0; lcid < MAX_NUM_LCID; ++lcid) { // loop over all the logical channels - rlc_status = mac_rlc_status_ind(Mod_id, rnti, Mod_id, frameP, subframeP, - ENB_FLAG_YES, MBMS_FLAG_NO, lcid, 0,0, 0 - ); - UE_template->dl_buffer_info[lcid] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel + /* loop over all activated logical channels */ + for (int i = 0; i < UE_sched_ctrl->dl_lc_num; ++i) { + const int lcid = UE_sched_ctrl->dl_lc_ids[i]; + const mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(Mod_id, + UE_template->rnti, + Mod_id, + frameP, + subframeP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + 0, + 0 + ); + UE_template->dl_buffer_info[lcid] = rlc_status.bytes_in_buffer; UE_template->dl_pdus_in_buffer[lcid] = rlc_status.pdus_in_buffer; UE_template->dl_buffer_head_sdu_creation_time[lcid] = rlc_status.head_sdu_creation_time; UE_template->dl_buffer_head_sdu_creation_time_max = cmax(UE_template->dl_buffer_head_sdu_creation_time_max, rlc_status.head_sdu_creation_time); UE_template->dl_buffer_head_sdu_remaining_size_to_send[lcid] = rlc_status.head_sdu_remaining_size_to_send; UE_template->dl_buffer_head_sdu_is_segmented[lcid] = rlc_status.head_sdu_is_segmented; - UE_template->dl_buffer_total += UE_template->dl_buffer_info[lcid]; //storing the total dlsch buffer + UE_template->dl_buffer_total += UE_template->dl_buffer_info[lcid]; UE_template->dl_pdus_total += UE_template->dl_pdus_in_buffer[lcid]; -#ifdef DEBUG_eNB_SCHEDULER + /* update the number of bytes in the UE_sched_ctrl. The DLSCH will use + * this to request the corresponding data from the RLC, and this might be + * limited in the preprocessor */ + UE_sched_ctrl->dl_lc_bytes[i] = rlc_status.bytes_in_buffer; + +#ifdef DEBUG_eNB_SCHEDULER /* note for dl_buffer_head_sdu_remaining_size_to_send[lcid] : * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent */ if (UE_template->dl_buffer_info[lcid] > 0) LOG_D(MAC, - "[eNB %d][SLICE %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n", - Mod_id, RC.mac[Mod_id]->slice_info.dl[slice_idx].id, frameP, + "[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n", + Mod_id, frameP, subframeP, UE_id, lcid, UE_template->dl_pdus_in_buffer[lcid], UE_template->dl_buffer_info[lcid], UE_template->dl_buffer_head_sdu_creation_time[lcid], UE_template->dl_buffer_head_sdu_remaining_size_to_send[lcid], UE_template->dl_buffer_head_sdu_is_segmented[lcid]); - #endif } @@ -165,1914 +303,572 @@ store_dlsch_buffer(module_id_t Mod_id, } } -int cqi2mcs(int cqi) { - return cqi_to_mcs[cqi]; -} - -// This function returns the estimated number of RBs required by each UE for downlink scheduling -void -assign_rbs_required(module_id_t Mod_id, - int slice_idx, - frame_t frameP, - sub_frame_t subframe, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - int min_rb_unit[NFAPI_CC_MAX]) { - uint16_t TBS = 0; - int UE_id, n, i, j, CC_id, pCCid, tmp; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - slice_info_t *sli = &RC.mac[Mod_id]->slice_info; - eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j; - int N_RB_DL; - - // clear rb allocations across all CC_id - for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id] != TRUE) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - pCCid = UE_PCCID(Mod_id, UE_id); - - //update CQI information across component carriers - for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) { - CC_id = UE_list->ordered_CCids[n][UE_id]; - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - // eNB_UE_stats->dlsch_mcs1 = cmin(cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]], sli->dl[slice_idx].maxmcs); - eNB_UE_stats->dlsch_mcs1 = cmin(cqi2mcs(UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]), sli->dl[slice_idx].maxmcs); - } - - // provide the list of CCs sorted according to MCS - for (i = 0; i < UE_list->numactiveCCs[UE_id]; ++i) { - eNB_UE_stats_i = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]][UE_id]; - - for (j = i + 1; j < UE_list->numactiveCCs[UE_id]; j++) { - DevAssert(j < NFAPI_CC_MAX); - eNB_UE_stats_j = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id]; - - if (eNB_UE_stats_j->dlsch_mcs1 > eNB_UE_stats_i->dlsch_mcs1) { - tmp = UE_list->ordered_CCids[i][UE_id]; - UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id]; - UE_list->ordered_CCids[j][UE_id] = tmp; - } - } - } - - if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total > 0) { - LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id); - - for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - - if (eNB_UE_stats->dlsch_mcs1 == 0) { - nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small - } else { - nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id]; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]); - LOG_D(MAC, - "[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n", - UE_id, CC_id, - UE_list->UE_template[pCCid][UE_id].dl_buffer_total, - nb_rbs_required[CC_id][UE_id], - eNB_UE_stats->dlsch_mcs1, TBS); - N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); - UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx] = - nb_rbs_allowed_slice(sli->dl[slice_idx].pct, N_RB_DL); - - /* calculating required number of RBs for each UE */ - while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) { - nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id]; - - if (nb_rbs_required[CC_id][UE_id] > UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]) { - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]); - nb_rbs_required[CC_id][UE_id] = UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]; - break; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]); - } // end of while - - LOG_D(MAC, - "[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n", - Mod_id, frameP, UE_id, CC_id, min_rb_unit[CC_id], - nb_rbs_required[CC_id][UE_id], TBS, - eNB_UE_stats->dlsch_mcs1); - sli->pre_processor_results[slice_idx].mcs[CC_id][UE_id] = eNB_UE_stats->dlsch_mcs1; - } - } - } -} - - -// This function scans all CC_ids for a particular UE to find the maximum round index of its HARQ processes -int -maxround(module_id_t Mod_id, uint16_t rnti, int frame, - sub_frame_t subframe) { - uint8_t round, round_max = 0, UE_id; - int CC_id, harq_pid; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - COMMON_channels_t *cc; - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - cc = &RC.mac[Mod_id]->common_channels[CC_id]; - UE_id = find_UE_id(Mod_id, rnti); - - if(UE_id == -1) - continue; - - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frame,subframe); - round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; - - if (round > round_max) { - round_max = round; - } - } - - return round_max; -} - -int -maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, - sub_frame_t sched_subframe) { - uint8_t round, round_max = 0, UE_id; - int CC_id, harq_pid; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - COMMON_channels_t *cc; - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - cc = &RC.mac[Mod_id]->common_channels[CC_id]; - UE_id = find_UE_id(Mod_id, rnti); - - if(UE_id == -1) - continue; - - harq_pid = subframe2harqpid(cc, sched_frame, sched_subframe); - round = UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; - - if (round > round_max) { - round_max = round; - } - } - - return round_max; -} - -// This function scans all CC_ids for a particular UE to find the maximum DL CQI -// it returns -1 if the UE is not found in PHY layer (get_eNB_UE_stats gives NULL) -int maxcqi(module_id_t Mod_id, int32_t UE_id) { - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - int CC_id, n; - int CQI = 0; - - for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) { - CC_id = UE_list->ordered_CCids[n][UE_id]; - - if (UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id] > CQI) { - CQI = UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; - } - } - - return CQI; -} - -long min_lcgidpriority(module_id_t Mod_id, int32_t UE_id) { - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - int i; - int pCC_id = UE_PCCID(Mod_id, UE_id); - long ret = UE_list->UE_template[pCC_id][UE_id].lcgidpriority[0]; - - for (i = 1; i < 11; ++i) { - if (UE_list->UE_template[pCC_id][UE_id].lcgidpriority[i] < ret) - ret = UE_list->UE_template[pCC_id][UE_id].lcgidpriority[i]; - } - - return ret; -} - -struct sort_ue_dl_params { - int Mod_idP; - int frameP; - int subframeP; - int slice_idx; -}; - -static int ue_dl_compare(const void *_a, const void *_b, void *_params) { - struct sort_ue_dl_params *params = _params; - UE_list_t *UE_list = &RC.mac[params->Mod_idP]->UE_list; - int i; - int slice_idx = params->slice_idx; - int UE_id1 = *(const int *) _a; - int UE_id2 = *(const int *) _b; - int rnti1 = UE_RNTI(params->Mod_idP, UE_id1); - int pCC_id1 = UE_PCCID(params->Mod_idP, UE_id1); - int round1 = maxround(params->Mod_idP, rnti1, params->frameP, params->subframeP); - int rnti2 = UE_RNTI(params->Mod_idP, UE_id2); - int pCC_id2 = UE_PCCID(params->Mod_idP, UE_id2); - int round2 = maxround(params->Mod_idP, rnti2, params->frameP, params->subframeP); - int cqi1 = maxcqi(params->Mod_idP, UE_id1); - int cqi2 = maxcqi(params->Mod_idP, UE_id2); - long lcgid1 = min_lcgidpriority(params->Mod_idP, UE_id1); - long lcgid2 = min_lcgidpriority(params->Mod_idP, UE_id2); - - for (i = 0; i < CR_NUM; ++i) { - switch (UE_list->sorting_criteria[slice_idx][i]) { - case CR_ROUND : - if (round1 > round2) - return -1; - - if (round1 < round2) - return 1; - - break; - - case CR_SRB12 : - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + - UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] > - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) - return -1; - - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + - UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) - return 1; - - break; - - case CR_HOL : - if (UE_list-> UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max > - UE_list-> UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) - return -1; - - if (UE_list-> UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max < - UE_list-> UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) - return 1; - - break; - - case CR_LC : - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total > - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) - return -1; - - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) - return 1; - - break; - - case CR_CQI : - if (cqi1 > cqi2) - return -1; - - if (cqi1 < cqi2) - return 1; - - break; - - case CR_LCP : - if (lcgid1 < lcgid2) - return -1; - - if (lcgid1 > lcgid2) - return 1; - - default : - break; - } - } - - return 0; -} - -void decode_sorting_policy(module_id_t Mod_idP, int slice_idx) { - int i; - UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list; - uint32_t policy = RC.mac[Mod_idP]->slice_info.dl[slice_idx].sorting; - uint32_t mask = 0x0000000F; - uint16_t criterion; - - for (i = 0; i < CR_NUM; ++i) { - criterion = (uint16_t) (policy >> 4 * (CR_NUM - 1 - i) & mask); - - if (criterion >= CR_NUM) { - LOG_W(MAC, - "Invalid criterion in slice index %d ID %d policy, revert to default policy \n", - slice_idx, RC.mac[Mod_idP]->slice_info.dl[slice_idx].id); - RC.mac[Mod_idP]->slice_info.dl[slice_idx].sorting = 0x12345; - break; - } - - UE_list->sorting_criteria[slice_idx][i] = criterion; - } -} - -void decode_slice_positioning(module_id_t Mod_idP, - int slice_idx, - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]) { - uint8_t CC_id; - int RBG, start_frequency, end_frequency; - - // Init slice_alloc_mask - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_idP]; ++CC_id) { - for (RBG = 0; RBG < N_RBG_MAX; ++RBG) { - slice_allocation_mask[CC_id][RBG] = 0; - } - } - - start_frequency = RC.mac[Mod_idP]->slice_info.dl[slice_idx].pos_low; - end_frequency = RC.mac[Mod_idP]->slice_info.dl[slice_idx].pos_high; - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_idP]; ++CC_id) { - for (RBG = start_frequency; RBG <= end_frequency; ++RBG) { - slice_allocation_mask[CC_id][RBG] = 1; - } - } -} - -//----------------------------------------------------------------------------- -/* - * This function sorts the UEs in order, depending on their dlsch buffer and CQI - */ -void sort_UEs(module_id_t Mod_idP, - int slice_idx, - int frameP, - sub_frame_t subframeP) -//----------------------------------------------------------------------------- -{ - int list[MAX_MOBILES_PER_ENB]; - int list_size = 0; - struct sort_ue_dl_params params = {Mod_idP, frameP, subframeP, slice_idx}; - UE_list_t *UE_list = &(RC.mac[Mod_idP]->UE_list); - UE_sched_ctrl_t *UE_scheduling_control = NULL; - - for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) { - UE_scheduling_control = &(UE_list->UE_sched_ctrl[i]); - - /* Check CDRX configuration and if UE is in active time for this subframe */ - if (UE_scheduling_control->cdrx_configured == TRUE) { - if (UE_scheduling_control->in_active_time == FALSE) { - continue; - } - } - - if (UE_list->active[i] == TRUE && - UE_RNTI(Mod_idP, i) != NOT_A_RNTI && - UE_list->UE_sched_ctrl[i].ul_out_of_sync != 1 && - ue_dl_slice_membership(Mod_idP, i, slice_idx)) { - list[list_size++] = i; - } - } - - decode_sorting_policy(Mod_idP, slice_idx); - qsort_r(list, list_size, sizeof(int), ue_dl_compare, ¶ms); - - if (list_size) { - for (int i = 0; i < list_size - 1; ++i) { - UE_list->next[list[i]] = list[i + 1]; - } - - UE_list->next[list[list_size - 1]] = -1; - UE_list->head = list[0]; - } else { - UE_list->head = -1; - } -} - -void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id, - int slice_idx, - const uint8_t rbs_retx[NFAPI_CC_MAX]) { - int UE_id, CC_id, N_RB_DL, i; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_sched_ctrl_t *ue_sched_ctl; - uint16_t available_rbs; - - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); ++i) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); - available_rbs = nb_rbs_allowed_slice(RC.mac[Mod_id]->slice_info.dl[slice_idx].pct, N_RB_DL); - - if (rbs_retx[CC_id] < available_rbs) - ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx] = available_rbs - rbs_retx[CC_id]; - else - ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx] = 0; - } - } -} - -void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, - int slice_idx, - frame_t frameP, - sub_frame_t subframeP, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) { - int UE_id, CC_id; - int i; - rnti_t rnti; - uint8_t harq_pid, round; - uint16_t available_rbs[NFAPI_CC_MAX]; - uint8_t rbs_retx[NFAPI_CC_MAX]; - uint16_t average_rbs_per_user[NFAPI_CC_MAX]; - int total_ue_count[NFAPI_CC_MAX]; - int ue_count_newtx[NFAPI_CC_MAX]; - int ue_count_retx[NFAPI_CC_MAX]; - //uint8_t ue_retx_flag[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_sched_ctrl_t *ue_sched_ctl; - COMMON_channels_t *cc; - - // Reset - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - total_ue_count[CC_id] = 0; - ue_count_newtx[CC_id] = 0; - ue_count_retx[CC_id] = 0; - rbs_retx[CC_id] = 0; - average_rbs_per_user[CC_id] = 0; - available_rbs[CC_id] = 0; - //for (UE_id = 0; UE_id < NFAPI_CC_MAX; ++UE_id) { - // ue_retx_flag[CC_id][UE_id] = 0; - //} - } - - // Find total UE count, and account the RBs required for retransmissions - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - - if (rnti == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); ++i) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - cc = &RC.mac[Mod_id]->common_channels[CC_id]; - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - round = ue_sched_ctl->round[CC_id][harq_pid]; - - if (nb_rbs_required[CC_id][UE_id] > 0) { - total_ue_count[CC_id]++; - } - - if (round != 8) { - nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - rbs_retx[CC_id] += nb_rbs_required[CC_id][UE_id]; - ue_count_retx[CC_id]++; - //ue_retx_flag[CC_id][UE_id] = 1; - } else { - ue_count_newtx[CC_id]++; - } - } - } - - // PARTITIONING - // Reduces the available RBs according to slicing configuration - dlsch_scheduler_pre_processor_partitioning(Mod_id, slice_idx, rbs_retx); - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; ++CC_id) { - if (UE_list->head < 0) continue; // no UEs in list - - // max_rbs_allowed_slice is saved in every UE, so take it from the first one - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_list->head]; - available_rbs[CC_id] = ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx]; - } - - switch (RC.mac[Mod_id]->slice_info.dl[slice_idx].accounting) { - // If greedy scheduling, try to account all the required RBs - case POL_GREEDY: - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - - if (rnti == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - - if (available_rbs[CC_id] == 0) continue; - - nb_rbs_accounted[CC_id][UE_id] = cmin(nb_rbs_required[CC_id][UE_id], available_rbs[CC_id]); - available_rbs[CC_id] -= nb_rbs_accounted[CC_id][UE_id]; - } - } - - break; - - // Use the old, fair algorithm - // Loop over all active UEs and account the avg number of RBs to each UE, based on all non-retx UEs. - // case POL_FAIR: - default: - - // FIXME: This is not ideal, why loop on UEs to find average_rbs_per_user[], that is per-CC? - // TODO: Look how to loop on active CCs only without using the UE_num_active_CC() function. - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - - if (rnti == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); ++i) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - available_rbs[CC_id] = ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx]; - - if (ue_count_newtx[CC_id] == 0) { - average_rbs_per_user[CC_id] = 0; - } else if (min_rb_unit[CC_id]*ue_count_newtx[CC_id] <= available_rbs[CC_id]) { - average_rbs_per_user[CC_id] = (uint16_t)floor(available_rbs[CC_id]/ue_count_newtx[CC_id]); - } else { - // consider the total number of use that can be scheduled UE - average_rbs_per_user[CC_id] = (uint16_t)min_rb_unit[CC_id]; - } - } - } - - // note: nb_rbs_required is assigned according to total_buffer_dl - // extend nb_rbs_required to capture per LCID RB required - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - - if (rnti == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - nb_rbs_accounted[CC_id][UE_id] = cmin(average_rbs_per_user[CC_id], nb_rbs_required[CC_id][UE_id]); - } - } - - break; - } - - // Check retransmissions - // TODO: Do this once at the beginning - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - - if (rnti == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - cc = &RC.mac[Mod_id]->common_channels[CC_id]; - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - round = ue_sched_ctl->round[CC_id][harq_pid]; - - // control channel or retransmission - /* TODO: do we have to check for retransmission? */ - if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round != 8) { - nb_rbs_accounted[CC_id][UE_id] = nb_rbs_required[CC_id][UE_id]; - } - } - } -} - -void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, - int slice_idx, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { - int UE_id, CC_id; - int i; -#ifdef TM5 - uint8_t transmission_mode; -#endif - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]; - int N_RBG[NFAPI_CC_MAX]; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - decode_slice_positioning(Mod_id, slice_idx, slice_allocation_mask); - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; - N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); - } - - // Try to allocate accounted RBs - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - nb_rbs_remaining[CC_id][UE_id] = nb_rbs_accounted[CC_id][UE_id]; -#ifdef TM5 - transmission_mode = get_tmode(Mod_id, CC_id, UE_id); -#endif - - if (nb_rbs_required[CC_id][UE_id] > 0) - LOG_D(MAC, - "Step 1: nb_rbs_remaining[%d][%d]= %d (accounted %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n", - CC_id, - UE_id, - nb_rbs_remaining[CC_id][UE_id], - nb_rbs_accounted[CC_id][UE_id], - nb_rbs_required[CC_id][UE_id], - UE_list->UE_sched_ctrl[UE_id].pre_nb_available_rbs[CC_id], - N_RBG[CC_id], - min_rb_unit[CC_id]); - - LOG_T(MAC, "calling dlsch_scheduler_pre_processor_allocate .. \n "); - dlsch_scheduler_pre_processor_allocate(Mod_id, - UE_id, - CC_id, - N_RBG[CC_id], - min_rb_unit[CC_id], - nb_rbs_required, - nb_rbs_remaining, - rballoc_sub, - slice_allocation_mask, - MIMO_mode_indicator); -#ifdef TM5 - - // data chanel TM5: to be revisited - if ((round == 0) && - (transmission_mode == 5) && - (ue_sched_ctl->dl_pow_off[CC_id] != 1)) { - for (j = 0; j < N_RBG[CC_id]; j += 2) { - if ((((j == (N_RBG[CC_id] - 1)) - && (rballoc_sub[CC_id][j] == 0) - && (ue_sched_ctl-> - rballoc_sub_UE[CC_id][j] == 0)) - || ((j < (N_RBG[CC_id] - 1)) - && (rballoc_sub[CC_id][j + 1] == 0) - && - (ue_sched_ctl->rballoc_sub_UE - [CC_id][j + 1] == 0))) - && (nb_rbs_remaining[CC_id][UE_id] - > 0)) { - for (i = UE_list->next[UE_id + 1]; i >= 0; - i = UE_list->next[i]) { - UE_id2 = i; - rnti2 = UE_RNTI(Mod_id, UE_id2); - ue_sched_ctl2 = - &UE_list->UE_sched_ctrl[UE_id2]; - round2 = ue_sched_ctl2->round[CC_id]; - - if (rnti2 == NOT_A_RNTI) - continue; - - if (UE_list-> - UE_sched_ctrl - [UE_id2].ul_out_of_sync == 1) - continue; - - eNB_UE_stats2 = - UE_list-> - eNB_UE_stats[CC_id][UE_id2]; - //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0); - - if ((mac_eNB_get_rrc_status - (Mod_id, - rnti2) >= RRC_RECONFIGURED) - && (round2 == 0) - && - (get_tmode(Mod_id, CC_id, UE_id2) - == 5) - && (ue_sched_ctl-> - dl_pow_off[CC_id] != 1)) { - if ((((j == (N_RBG[CC_id] - 1)) - && - (ue_sched_ctl->rballoc_sub_UE - [CC_id][j] == 0)) - || ((j < (N_RBG[CC_id] - 1)) - && - (ue_sched_ctl-> - rballoc_sub_UE[CC_id][j + - 1] - == 0))) - && - (nb_rbs_remaining - [CC_id] - [UE_id2] > 0)) { - if ((((eNB_UE_stats2-> - DL_pmi_single ^ - eNB_UE_stats1-> - DL_pmi_single) - << (14 - j)) & 0xc000) == 0x4000) { //MU-MIMO only for 25 RBs configuration - rballoc_sub[CC_id][j] = 1; - ue_sched_ctl-> - rballoc_sub_UE[CC_id] - [j] = 1; - ue_sched_ctl2-> - rballoc_sub_UE[CC_id] - [j] = 1; - MIMO_mode_indicator[CC_id] - [j] = 0; - - if (j < N_RBG[CC_id] - 1) { - rballoc_sub[CC_id][j + - 1] = - 1; - ue_sched_ctl-> - rballoc_sub_UE - [CC_id][j + 1] = 1; - ue_sched_ctl2->rballoc_sub_UE - [CC_id][j + 1] = 1; - MIMO_mode_indicator - [CC_id][j + 1] - = 0; - } - - ue_sched_ctl-> - dl_pow_off[CC_id] - = 0; - ue_sched_ctl2-> - dl_pow_off[CC_id] - = 0; - - if ((j == N_RBG[CC_id] - 1) - && ((N_RB_DL == 25) - || (N_RB_DL == - 50))) { - nb_rbs_remaining - [CC_id][UE_id] = - nb_rbs_remaining - [CC_id][UE_id] - - min_rb_unit[CC_id] - + 1; - ue_sched_ctl->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl->pre_nb_available_rbs - [CC_id] + - min_rb_unit[CC_id] - - 1; - nb_rbs_remaining - [CC_id][UE_id2] = - nb_rbs_remaining - [CC_id][UE_id2] - - min_rb_unit[CC_id] - + 1; - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] + - min_rb_unit[CC_id] - - 1; - } else { - nb_rbs_remaining - [CC_id][UE_id] = - nb_rbs_remaining - [CC_id][UE_id] - 4; - ue_sched_ctl->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl->pre_nb_available_rbs - [CC_id] + 4; - nb_rbs_remaining - [CC_id][UE_id2] = - nb_rbs_remaining - [CC_id][UE_id2] - - 4; - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] + 4; - } - - break; - } - } - } - } - } - } - } - -#endif - } - } -} - -void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id, - int slice_idx, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { - int UE_id, CC_id; - int i; -#ifdef TM5 - uint8_t transmission_mode; -#endif - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - int N_RBG[NFAPI_CC_MAX]; - slice_info_t *sli = &RC.mac[Mod_id]->slice_info; - uint8_t (*slice_allocation_mask)[N_RBG_MAX] = sli->pre_processor_results[slice_idx].slice_allocation_mask; - decode_slice_positioning(Mod_id, slice_idx, slice_allocation_mask); - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; - N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); - } - - // Remaining RBs are allocated to high priority UEs - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - nb_rbs_remaining[CC_id][UE_id] = - nb_rbs_required[CC_id][UE_id] - nb_rbs_accounted[CC_id][UE_id] + nb_rbs_remaining[CC_id][UE_id]; - - if (nb_rbs_remaining[CC_id][UE_id] < 0) - abort(); - -#ifdef TM5 - transmission_mode = get_tmode(Mod_id, CC_id, UE_id); -#endif - - if (nb_rbs_required[CC_id][UE_id] > 0) - LOG_D(MAC, - "Step 2: nb_rbs_remaining[%d][%d]= %d (accounted %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n", - CC_id, - UE_id, - nb_rbs_remaining[CC_id][UE_id], - nb_rbs_accounted[CC_id][UE_id], - nb_rbs_required[CC_id][UE_id], - UE_list->UE_sched_ctrl[UE_id].pre_nb_available_rbs[CC_id], - N_RBG[CC_id], - min_rb_unit[CC_id]); - - LOG_T(MAC, "calling dlsch_scheduler_pre_processor_allocate .. \n "); - dlsch_scheduler_pre_processor_allocate(Mod_id, - UE_id, - CC_id, - N_RBG[CC_id], - min_rb_unit[CC_id], - nb_rbs_required, - nb_rbs_remaining, - rballoc_sub, - slice_allocation_mask, - MIMO_mode_indicator); -#ifdef TM5 - - // data chanel TM5: to be revisited - if ((round == 0) && - (transmission_mode == 5) && - (ue_sched_ctl->dl_pow_off[CC_id] != 1)) { - for (j = 0; j < N_RBG[CC_id]; j += 2) { - if ((((j == (N_RBG[CC_id] - 1)) - && (rballoc_sub[CC_id][j] == 0) - && (ue_sched_ctl-> - rballoc_sub_UE[CC_id][j] == 0)) - || ((j < (N_RBG[CC_id] - 1)) - && (rballoc_sub[CC_id][j + 1] == 0) - && - (ue_sched_ctl->rballoc_sub_UE - [CC_id][j + 1] == 0))) - && (nb_rbs_remaining[CC_id][UE_id] - > 0)) { - for (i = UE_list->next[UE_id + 1]; i >= 0; - i = UE_list->next[i]) { - UE_id2 = i; - rnti2 = UE_RNTI(Mod_id, UE_id2); - ue_sched_ctl2 = - &UE_list->UE_sched_ctrl[UE_id2]; - round2 = ue_sched_ctl2->round[CC_id]; - - if (rnti2 == NOT_A_RNTI) - continue; - - if (UE_list-> - UE_sched_ctrl - [UE_id2].ul_out_of_sync == 1) - continue; - - eNB_UE_stats2 = - UE_list-> - eNB_UE_stats[CC_id][UE_id2]; - //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0); - - if ((mac_eNB_get_rrc_status - (Mod_id, - rnti2) >= RRC_RECONFIGURED) - && (round2 == 0) - && - (get_tmode(Mod_id, CC_id, UE_id2) - == 5) - && (ue_sched_ctl-> - dl_pow_off[CC_id] != 1)) { - if ((((j == (N_RBG[CC_id] - 1)) - && - (ue_sched_ctl->rballoc_sub_UE - [CC_id][j] == 0)) - || ((j < (N_RBG[CC_id] - 1)) - && - (ue_sched_ctl-> - rballoc_sub_UE[CC_id][j + - 1] - == 0))) - && - (nb_rbs_remaining - [CC_id] - [UE_id2] > 0)) { - if ((((eNB_UE_stats2-> - DL_pmi_single ^ - eNB_UE_stats1-> - DL_pmi_single) - << (14 - j)) & 0xc000) == 0x4000) { //MU-MIMO only for 25 RBs configuration - rballoc_sub[CC_id][j] = 1; - ue_sched_ctl-> - rballoc_sub_UE[CC_id] - [j] = 1; - ue_sched_ctl2-> - rballoc_sub_UE[CC_id] - [j] = 1; - MIMO_mode_indicator[CC_id] - [j] = 0; - - if (j < N_RBG[CC_id] - 1) { - rballoc_sub[CC_id][j + - 1] = - 1; - ue_sched_ctl-> - rballoc_sub_UE - [CC_id][j + 1] = 1; - ue_sched_ctl2->rballoc_sub_UE - [CC_id][j + 1] = 1; - MIMO_mode_indicator - [CC_id][j + 1] - = 0; - } - - ue_sched_ctl-> - dl_pow_off[CC_id] - = 0; - ue_sched_ctl2-> - dl_pow_off[CC_id] - = 0; - - if ((j == N_RBG[CC_id] - 1) - && ((N_RB_DL == 25) - || (N_RB_DL == - 50))) { - nb_rbs_remaining - [CC_id][UE_id] = - nb_rbs_remaining - [CC_id][UE_id] - - min_rb_unit[CC_id] - + 1; - ue_sched_ctl->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl->pre_nb_available_rbs - [CC_id] + - min_rb_unit[CC_id] - - 1; - nb_rbs_remaining - [CC_id][UE_id2] = - nb_rbs_remaining - [CC_id][UE_id2] - - min_rb_unit[CC_id] - + 1; - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] + - min_rb_unit[CC_id] - - 1; - } else { - nb_rbs_remaining - [CC_id][UE_id] = - nb_rbs_remaining - [CC_id][UE_id] - 4; - ue_sched_ctl->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl->pre_nb_available_rbs - [CC_id] + 4; - nb_rbs_remaining - [CC_id][UE_id2] = - nb_rbs_remaining - [CC_id][UE_id2] - - 4; - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] + 4; - } - - break; - } - } - } - } - } - } - } - -#endif - } - } -} // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done void dlsch_scheduler_pre_processor(module_id_t Mod_id, - int slice_idx, + int CC_id, frame_t frameP, - sub_frame_t subframeP, - int *mbsfn_flag, - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) { - int UE_id; - uint8_t CC_id; - uint16_t i, j; - int min_rb_unit[NFAPI_CC_MAX]; - eNB_MAC_INST *eNB = RC.mac[Mod_id]; - slice_info_t *sli = &eNB->slice_info; - uint16_t (*nb_rbs_required)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_required; - uint16_t (*nb_rbs_accounted)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_accounted; - uint16_t (*nb_rbs_remaining)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_remaining; - uint8_t (*MIMO_mode_indicator)[N_RBG_MAX] = sli->pre_processor_results[slice_idx].MIMO_mode_indicator; - UE_list_t *UE_list = &eNB->UE_list; - UE_sched_ctrl_t *ue_sched_ctl; - // int rrc_status = RRC_IDLE; -#ifdef TM5 - int harq_pid1 = 0; - int round1 = 0, round2 = 0; - int UE_id2; - uint16_t i1, i2, i3; - rnti_t rnti1, rnti2; - LTE_eNB_UE_stats *eNB_UE_stats1 = NULL; - LTE_eNB_UE_stats *eNB_UE_stats2 = NULL; - UE_sched_ctrl_t *ue_sched_ctl1, *ue_sched_ctl2; -#endif - // Initialize scheduling information for all active UEs - memset(&sli->pre_processor_results[slice_idx], 0, sizeof(sli->pre_processor_results[slice_idx])); - // FIXME: After the memset above, some of the resets in reset() are redundant - dlsch_scheduler_pre_processor_reset(Mod_id, - slice_idx, - frameP, - subframeP, - min_rb_unit, - nb_rbs_required, - rballoc_sub, - MIMO_mode_indicator, - mbsfn_flag); // FIXME: Not sure if useful - // STATUS - // Store the DLSCH buffer for each logical channel - store_dlsch_buffer(Mod_id, - slice_idx, - frameP, - subframeP); - // Calculate the number of RBs required by each UE on the basis of logical channel's buffer - assign_rbs_required(Mod_id, - slice_idx, - frameP, - subframeP, - nb_rbs_required, - min_rb_unit); - // Sorts the user on the basis of dlsch logical channel buffer and CQI - sort_UEs(Mod_id, - slice_idx, - frameP, - subframeP); - // ACCOUNTING - // This procedure decides the number of RBs to allocate - dlsch_scheduler_pre_processor_accounting(Mod_id, - slice_idx, - frameP, - subframeP, - min_rb_unit, - nb_rbs_required, - nb_rbs_accounted); - // POSITIONING - // This procedure does the main allocation of the RBs - dlsch_scheduler_pre_processor_positioning(Mod_id, - slice_idx, - min_rb_unit, - nb_rbs_required, - nb_rbs_accounted, - nb_rbs_remaining, - rballoc_sub, - MIMO_mode_indicator); + sub_frame_t subframeP) { + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); - // SHARING - // If there are available RBs left in the slice, allocate them to the highest priority UEs - if (eNB->slice_info.intraslice_share_active) { - dlsch_scheduler_pre_processor_intraslice_sharing(Mod_id, - slice_idx, - min_rb_unit, - nb_rbs_required, - nb_rbs_accounted, - nb_rbs_remaining, - rballoc_sub, - MIMO_mode_indicator); - } + store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP); -#ifdef TM5 + UE_list_t UE_to_sched; + UE_to_sched.head = -1; + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + UE_to_sched.next[i] = -1; - // This has to be revisited!!!! - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - COMMON_channels_t *cc = &eNB->common_channels[CC_id]; - int N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); - i1 = 0; - i2 = 0; - i3 = 0; + int first = 1; + int last_UE_id = -1; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id]; - for (j = 0; j < N_RBG; j++) { - if (MIMO_mode_indicator[CC_id][j] == 2) { - i1++; - } else if (MIMO_mode_indicator[CC_id][j] == 1) { - i2++; - } else if (MIMO_mode_indicator[CC_id][j] == 0) { - i3++; - } + /* initialize per-UE scheduling information */ + ue_sched_ctrl->pre_nb_available_rbs[CC_id] = 0; + ue_sched_ctrl->dl_pow_off[CC_id] = 2; + memset(ue_sched_ctrl->rballoc_sub_UE[CC_id], 0, sizeof(ue_sched_ctrl->rballoc_sub_UE[CC_id])); + ue_sched_ctrl->pre_dci_dl_pdu_idx = -1; + + const rnti_t rnti = UE_RNTI(Mod_id, UE_id); + if (rnti == NOT_A_RNTI) { + LOG_E(MAC, "UE %d has RNTI NOT_A_RNTI!\n", UE_id); + continue; + } + if (UE_info->active[UE_id] != TRUE) { + LOG_E(MAC, "UE %d RNTI %x is NOT active!\n", UE_id, rnti); + continue; + } + if (ue_template->rach_resource_type > 0) { + LOG_D(MAC, + "UE %d is RACH resource type %d\n", + UE_id, + ue_template->rach_resource_type); + continue; + } + if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_CONNECTED) { + LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n", UE_id); + continue; } - if (i1 < N_RBG) { - if (i2 > 0 && i3 == 0) { - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions + 1; - } else if (i3 > 0) { - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions + 1; - } - } else if (i3 == N_RBG && i1 == 0 && i2 == 0) { - PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions + 1; + /* define UEs to schedule */ + if (first) { + first = 0; + UE_to_sched.head = UE_id; + } else { + UE_to_sched.next[last_UE_id] = UE_id; } - - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions + 1; + UE_to_sched.next[UE_id] = -1; + last_UE_id = UE_id; } -#endif + if (UE_to_sched.head < 0) + return; - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id]; - COMMON_channels_t *cc = &eNB->common_channels[CC_id]; - int N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); - - if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0) { - LOG_D(MAC, "******************DL Scheduling Information for UE%d ************************\n", - UE_id); - LOG_D(MAC, "dl power offset UE%d = %d \n", - UE_id, - ue_sched_ctl->dl_pow_off[CC_id]); - LOG_D(MAC, "***********RB Alloc for every subband for UE%d ***********\n", - UE_id); - - for (j = 0; j < N_RBG; j++) { - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[UE_id] = rballoc_sub_UE[CC_id][UE_id][UE_id]; - LOG_D(MAC, "RB Alloc for UE%d and Subband%d = %d\n", - UE_id, j, - ue_sched_ctl->rballoc_sub_UE[CC_id][j]); - } - - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id]; - LOG_D(MAC, "[eNB %d][SLICE %d]Total RBs allocated for UE%d = %d\n", - Mod_id, - eNB->slice_info.dl[slice_idx].id, - UE_id, - ue_sched_ctl->pre_nb_available_rbs[CC_id]); - } - } + uint8_t *vrb_map = RC.mac[Mod_id]->common_channels[CC_id].vrb_map; + uint8_t rbgalloc_mask[N_RBG_MAX]; + int n_rbg_sched = 0; + for (int i = 0; i < N_RBG; i++) { + // calculate mask: init to one + "AND" with vrb_map: + // if any RB in vrb_map is blocked (1), the current RBG will be 0 + rbgalloc_mask[i] = 1; + for (int j = 0; j < RBGsize; j++) + rbgalloc_mask[i] &= !vrb_map[RBGsize * i + j]; + n_rbg_sched += rbgalloc_mask[i]; } -} -#define SF0_LIMIT 1 + round_robin_dl(Mod_id, + CC_id, + frameP, + subframeP, + &UE_to_sched, + 4, // max_num_ue + n_rbg_sched, + rbgalloc_mask); -void -dlsch_scheduler_pre_processor_reset(module_id_t module_idP, - int slice_idx, - frame_t frameP, - sub_frame_t subframeP, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX], - int *mbsfn_flag) { - int UE_id; - uint8_t CC_id; - int i, j; - UE_list_t *UE_list; - UE_sched_ctrl_t *ue_sched_ctl; - int N_RB_DL, RBGsize, RBGsize_last; - int N_RBG[NFAPI_CC_MAX]; -#ifdef SF0_LIMIT - int sf0_lower, sf0_upper; -#endif - rnti_t rnti; - uint8_t *vrb_map; - COMMON_channels_t *cc; + // the following block is meant for validation of the pre-processor to check + // whether all UE allocations are non-overlapping and is not necessary for + // scheduling functionality +#ifdef DEBUG_eNB_SCHEDULER + char t[26] = "_________________________"; + t[N_RBG] = 0; + for (int i = 0; i < N_RBG; i++) + for (int j = 0; j < RBGsize; j++) + if (vrb_map[RBGsize*i+j] != 0) + t[i] = 'x'; + int print = 0; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + const UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - // - for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - // initialize harq_pid and round - cc = &RC.mac[module_idP]->common_channels[CC_id]; - N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); - min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); - - if (mbsfn_flag[CC_id] > 0) // If this CC is allocated for MBSFN skip it here + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) continue; - for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) { - UE_list = &RC.mac[module_idP]->UE_list; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - rnti = UE_RNTI(module_idP, UE_id); + LOG_D(MAC, + "%4d.%d UE%d %d RBs allocated, pre MCS %d\n", + frameP, + subframeP, + UE_id, + ue_sched_ctrl->pre_nb_available_rbs[CC_id], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1); - if (rnti == NOT_A_RNTI) + print = 1; + + for (int i = 0; i < N_RBG; i++) { + if (!ue_sched_ctrl->rballoc_sub_UE[CC_id][i]) continue; - - if (UE_list->active[UE_id] != TRUE) - continue; - - if (!ue_dl_slice_membership(module_idP, UE_id, slice_idx)) - continue; - - LOG_D(MAC, "Running preprocessor for UE %d (%x)\n", UE_id, rnti); - - // initialize harq_pid and round - if (ue_sched_ctl->ta_timer) - ue_sched_ctl->ta_timer--; - - /* - eNB_UE_stats *eNB_UE_stats; - - if (eNB_UE_stats == NULL) - return; - - - mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti, - frameP,subframeP, - &ue_sched_ctl->harq_pid[CC_id], - &ue_sched_ctl->round[CC_id], - openair_harq_DL); - - - if (ue_sched_ctl->ta_timer == 0) { - - // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ... - - ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY - switch (N_RB_DL) { - case 6: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update; - break; - - case 15: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2; - break; - - case 25: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4; - break; - - case 50: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8; - break; - - case 75: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12; - break; - - case 100: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16; - break; - } - // clear the update in case PHY does not have a new measurement after timer expiry - eNB_UE_stats->timing_advance_update = 0; - } - else { - ue_sched_ctl->ta_timer--; - ue_sched_ctl->ta_update =0; // don't trigger a timing advance command - } - - - if (UE_id==0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update); - } - */ - nb_rbs_required[CC_id][UE_id] = 0; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; - ue_sched_ctl->dl_pow_off[CC_id] = 2; - - for (i = 0; i < N_RBG[CC_id]; i++) { - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; - } - } - - N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); -#ifdef SF0_LIMIT - - switch (N_RBG[CC_id]) { - case 6: - sf0_lower = 0; - sf0_upper = 5; - break; - - case 8: - sf0_lower = 2; - sf0_upper = 5; - break; - - case 13: - sf0_lower = 4; - sf0_upper = 7; - break; - - case 17: - sf0_lower = 7; - sf0_upper = 9; - break; - - case 25: - sf0_lower = 11; - sf0_upper = 13; - break; - - default: - AssertFatal(1 == 0, "unsupported RBs (%d)\n", N_RB_DL); - } - -#endif - - switch (N_RB_DL) { - case 6: - RBGsize = 1; - RBGsize_last = 1; - break; - - case 15: - RBGsize = 2; - RBGsize_last = 1; - break; - - case 25: - RBGsize = 2; - RBGsize_last = 1; - break; - - case 50: - RBGsize = 3; - RBGsize_last = 2; - break; - - case 75: - RBGsize = 4; - RBGsize_last = 3; - break; - - case 100: - RBGsize = 4; - RBGsize_last = 4; - break; - - default: - AssertFatal(1 == 0, "unsupported RBs (%d)\n", N_RB_DL); - } - - vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map; - - // Initialize Subbands according to VRB map - for (i = 0; i < N_RBG[CC_id]; i++) { - int rb_size = i == N_RBG[CC_id] - 1 ? RBGsize_last : RBGsize; -#ifdef SF0_LIMIT - - // for avoiding 6+ PRBs around DC in subframe 0 (avoid excessive errors) - /* TODO: make it proper - allocate those RBs, do not "protect" them, but - * compute number of available REs and limit MCS according to the - * TBS table 36.213 7.1.7.2.1-1 (can be done after pre-processor) - */ - if (subframeP == 0 && i >= sf0_lower && i <= sf0_upper) - rballoc_sub[CC_id][i] = 1; - -#endif - - // for SI-RNTI,RA-RNTI and P-RNTI allocations - for (j = 0; j < rb_size; j++) { - if (vrb_map[j + (i*RBGsize)] != 0) { - rballoc_sub[CC_id][i] = 1; - LOG_D(MAC, "Frame %d, subframe %d : vrb %d allocated\n", frameP, subframeP, j + (i*RBGsize)); - break; + for (int j = 0; j < RBGsize; j++) { + if (vrb_map[RBGsize*i+j] != 0) { + LOG_I(MAC, "%4d.%d DL scheduler allocation list: %s\n", frameP, subframeP, t); + LOG_E(MAC, "%4d.%d: UE %d allocated at locked RB %d/RBG %d\n", frameP, + subframeP, UE_id, RBGsize * i + j, i); } + vrb_map[RBGsize*i+j] = 1; } - - //LOG_D(MAC, "Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n", - //frameP, subframeP, CC_id, i, rballoc_sub[CC_id][i]); - MIMO_mode_indicator[CC_id][i] = 2; + t[i] = '0' + UE_id; } } + if (print) + LOG_D(MAC, "%4d.%d DL scheduler allocation list: %s\n", frameP, subframeP, t); +#endif } - -void -dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, - int UE_id, - uint8_t CC_id, - int N_RBG, - int min_rb_unit, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { - int i; - int tm = get_tmode(Mod_id, CC_id, UE_id); - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); - - for (i = 0; i < N_RBG; i++) { - if (rballoc_sub[CC_id][i] != 0) continue; - - if (ue_sched_ctl->rballoc_sub_UE[CC_id][i] != 0) continue; - - if (nb_rbs_remaining[CC_id][UE_id] <= 0) continue; - - if (ue_sched_ctl->pre_nb_available_rbs[CC_id] >= nb_rbs_required[CC_id][UE_id]) continue; - - if (ue_sched_ctl->dl_pow_off[CC_id] == 0) continue; - - if (slice_allocation_mask[CC_id][i] == 0) continue; - - if ((i == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { - // Allocating last, smaller RBG - if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) { - rballoc_sub[CC_id][i] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - MIMO_mode_indicator[CC_id][i] = 1; - - if (tm == 5) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - - nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit + 1; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1; - } - } else { - // Allocating a standard-sized RBG - if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) { - rballoc_sub[CC_id][i] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - MIMO_mode_indicator[CC_id][i] = 1; - - if (tm == 5) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - - nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit; - } - } - } -} - - /// ULSCH PRE_PROCESSOR -void ulsch_scheduler_pre_processor(module_id_t module_idP, - int slice_idx, +void calculate_max_mcs_min_rb(module_id_t mod_id, + int CC_id, + int bytes, + int phr, + int max_mcs, + int *mcs, + int max_rbs, + int *rb_index, + int *tx_power) { + const int Ncp = RC.mac[mod_id]->common_channels[CC_id].Ncp; + /* TODO shouldn't we consider the SRS or other quality indicators? */ + *mcs = max_mcs; + *rb_index = 2; + int tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); + + // fixme: set use_srs flag + *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); + + /* find maximum MCS */ + while ((phr - *tx_power < 0 || tbs > bytes) && *mcs > 3) { + mcs--; + tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); + *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); + } + + /* find minimum necessary RBs */ + while (tbs < bytes + && *rb_index < 32 + && rb_table[*rb_index] < max_rbs + && phr - *tx_power > 0) { + (*rb_index)++; + tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); + *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); + } + + /* Decrease if we went to far in last iteration */ + if (rb_table[*rb_index] > max_rbs) + (*rb_index)--; + + // 1 or 2 PRB with cqi enabled does not work well + if (rb_table[*rb_index] < 3) { + *rb_index = 2; //3PRB + } +} + +int pp_find_rb_table_index(int approximate) { + int lo = 2; + if (approximate <= rb_table[lo]) + return lo; + int hi = sizeof(rb_table) - 1; + if (approximate >= rb_table[hi]) + return hi; + int p = (hi + lo) / 2; + for (; lo + 1 != hi; p = (hi + lo) / 2) { + if (approximate <= rb_table[p]) + hi = p; + else + lo = p; + } + return p + 1; +} + +int g_start_ue_ul = -1; +int round_robin_ul(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + int sched_frame, + int sched_subframe, + UE_list_t *UE_list, + int max_num_ue, + int num_contig_rb, + contig_rbs_t *rbs) { + AssertFatal(num_contig_rb <= 2, "cannot handle more than two contiguous RB regions\n"); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + const int max_rb = num_contig_rb > 1 ? MAX(rbs[0].length, rbs[1].length) : rbs[0].length; + + /* for every UE: check whether we have to handle a retransmission (and + * allocate, if so). If not, compute how much RBs this UE would need */ + int rb_idx_required[MAX_MOBILES_PER_ENB]; + memset(rb_idx_required, 0, sizeof(rb_idx_required)); + int num_ue_req = 0; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id], + sched_frame, sched_subframe); + if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) { + /* this UE has a retransmission, allocate it right away */ + const int nb_rb = UE_template->nb_rb_ul[harq_pid]; + if (nb_rb == 0) { + LOG_E(MAC, + "%4d.%d UE %d retransmission of 0 RBs in round %d, ignoring\n", + sched_frame, sched_subframe, UE_id, + UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]); + continue; + } + const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_ulsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; // cannot allocate CCE + UE_template->pre_dci_ul_pdu_idx = idx; + if (rbs[0].length >= nb_rb) { // fits in first contiguous region + UE_template->pre_first_nb_rb_ul = rbs[0].start; + rbs[0].length -= nb_rb; + rbs[0].start += nb_rb; + } else if (num_contig_rb == 2 && rbs[1].length >= nb_rb) { // in second + UE_template->pre_first_nb_rb_ul = rbs[1].start; + rbs[1].length -= nb_rb; + rbs[1].start += nb_rb; + } else if (num_contig_rb == 2 + && rbs[1].start + rbs[1].length - rbs[0].start >= nb_rb) { // overlapping the middle + UE_template->pre_first_nb_rb_ul = rbs[0].start; + rbs[0].length = 0; + int ol = nb_rb - (rbs[1].start - rbs[0].start); // how much overlap in second region + if (ol > 0) { + rbs[1].length -= ol; + rbs[1].start += ol; + } + } else { + LOG_W(MAC, + "cannot allocate UL retransmission for UE %d (nb_rb %d)\n", + UE_id, + nb_rb); + UE_template->pre_dci_ul_pdu_idx = -1; // do not need CCE + RC.mac[Mod_id]->HI_DCI0_req[CC_id][subframe].hi_dci0_request_body.number_of_dci--; + continue; + } + LOG_D(MAC, "%4d.%d UE %d retx %d RBs at start %d\n", + sched_frame, + sched_subframe, + UE_id, + UE_template->pre_allocated_nb_rb_ul, + UE_template->pre_first_nb_rb_ul); + UE_template->pre_allocated_nb_rb_ul = nb_rb; + max_num_ue--; + if (max_num_ue == 0) /* in this case, cannot allocate any other UE anymore */ + return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); + continue; + } + + const int B = cmax(UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes, 0); + const int UE_to_be_scheduled = UE_is_to_be_scheduled(Mod_id, CC_id, UE_id); + if (B == 0 && !UE_to_be_scheduled) + continue; + + num_ue_req++; + + /* if UE has pending scheduling request then pre-allocate 3 RBs */ + if (B == 0 && UE_to_be_scheduled) { + UE_template->pre_assigned_mcs_ul = 10; /* use QPSK mcs only */ + rb_idx_required[UE_id] = 2; + //UE_template->pre_allocated_nb_rb_ul = 3; + continue; + } + + int mcs; + int rb_table_index; + int tx_power; + calculate_max_mcs_min_rb( + Mod_id, + CC_id, + B, + UE_template->phr_info, + UE_info->UE_sched_ctrl[UE_id].phr_received == 1 ? 20 : 10, + &mcs, + max_rb, + &rb_table_index, + &tx_power); + + UE_template->pre_assigned_mcs_ul = mcs; + rb_idx_required[UE_id] = rb_table_index; + //UE_template->pre_allocated_nb_rb_ul = rb_table[rb_table_index]; + /* only print log when PHR changed */ + static int phr = 0; + if (phr != UE_template->phr_info) { + phr = UE_template->phr_info; + LOG_D(MAC, "%d.%d UE %d CC %d: pre mcs %d, pre rb_table[%d]=%d RBs (phr %d, tx power %d, bytes %d)\n", + frame, + subframe, + UE_id, + CC_id, + UE_template->pre_assigned_mcs_ul, + UE_template->pre_allocated_rb_table_index_ul, + UE_template->pre_allocated_nb_rb_ul, + UE_template->phr_info, + tx_power, + B); + } + } + + if (num_ue_req == 0) + return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); + + // calculate how many users should be in both regions, and to maximize usage, + // go from the larger to the smaller one which at least will handle a single + // full load case better. + const int n = min(num_ue_req, max_num_ue); + int nr[2] = {n, 0}; + int step = 1; // the order if we have two regions + int start = 0; + int end = 1; + if (num_contig_rb > 1) { + // proportionally divide between both regions + int la = rbs[0].length > 0 ? rbs[0].length : 1; + int lb = rbs[1].length > 0 ? rbs[1].length : 1; + nr[1] = min(max(n/(la/lb + 1), 1), n - 1); + nr[0] = n - nr[1]; + step = la > lb ? 1 : -1; // 1: from 0 to 1, -1: from 1 to 0 + start = la > lb ? 0 : 1; + end = la > lb ? 2 : -1; + } + + if (g_start_ue_ul == -1) + g_start_ue_ul = UE_list->head; + int sUE_id = g_start_ue_ul; + int rb_idx_given[MAX_MOBILES_PER_ENB]; + memset(rb_idx_given, 0, sizeof(rb_idx_given)); + + for (int r = start; r != end; r += step) { + // don't allocate if we have too little RBs + if (rbs[r].length < 3) + continue; + if (nr[r] <= 0) + continue; + + UE_list_t UE_sched; + // average RB index: just below the index that fits all UEs + int start_idx = pp_find_rb_table_index(rbs[r].length / nr[r]) - 1; + int num_ue_sched = 0; + int rb_required_add = 0; + int *cur_UE = &UE_sched.head; + while (num_ue_sched < nr[r]) { + while (rb_idx_required[sUE_id] == 0) + sUE_id = next_ue_list_looped(UE_list, sUE_id); + const int cqi = UE_info->UE_sched_ctrl[sUE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_ulsch(Mod_id, CC_id, subframe, sUE_id, cqi); + if (idx < 0) { + LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", sUE_id); + nr[r]--; + sUE_id = next_ue_list_looped(UE_list, sUE_id); // next candidate + continue; + } + UE_info->UE_template[CC_id][sUE_id].pre_dci_ul_pdu_idx = idx; + *cur_UE = sUE_id; + cur_UE = &UE_sched.next[sUE_id]; + rb_idx_given[sUE_id] = min(start_idx, rb_idx_required[sUE_id]); + rb_required_add += rb_table[rb_idx_required[sUE_id]] - rb_table[rb_idx_given[sUE_id]]; + rbs[r].length -= rb_table[rb_idx_given[sUE_id]]; + num_ue_sched++; + sUE_id = next_ue_list_looped(UE_list, sUE_id); + } + *cur_UE = -1; + + /* give remaining RBs in RR fashion. Since we don't know in advance the + * amount of RBs we can give (the "step size" in rb_table is non-linear), go + * through all UEs and try to give a bit more. Continue until no UE can be + * given a higher index because the remaining RBs do not suffice to increase */ + int UE_id = UE_sched.head; + int rb_required_add_old; + do { + rb_required_add_old = rb_required_add; + for (int UE_id = UE_sched.head; UE_id >= 0; UE_id = UE_sched.next[UE_id]) { + if (rb_idx_given[UE_id] >= rb_idx_required[UE_id]) + continue; // this UE does not need more + const int new_idx = rb_idx_given[UE_id] + 1; + const int rb_inc = rb_table[new_idx] - rb_table[rb_idx_given[UE_id]]; + if (rbs[r].length < rb_inc) + continue; + rb_idx_given[UE_id] = new_idx; + rbs[r].length -= rb_inc; + rb_required_add -= rb_inc; + } + } while (rb_required_add != rb_required_add_old); + + for (UE_id = UE_sched.head; UE_id >= 0; UE_id = UE_sched.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + + /* MCS has been allocated previously */ + UE_template->pre_first_nb_rb_ul = rbs[r].start; + UE_template->pre_allocated_rb_table_index_ul = rb_idx_given[UE_id]; + UE_template->pre_allocated_nb_rb_ul = rb_table[rb_idx_given[UE_id]]; + rbs[r].start += rb_table[rb_idx_given[UE_id]]; + LOG_D(MAC, "%4d.%d UE %d allocated %d RBs start %d new start %d\n", + sched_frame, + sched_subframe, + UE_id, + UE_template->pre_allocated_nb_rb_ul, + UE_template->pre_first_nb_rb_ul, + rbs[r].start); + } + } + + /* if not all UEs could be allocated in this round */ + if (num_ue_req > max_num_ue) { + /* go to the first one we missed */ + for (int i = 0; i < max_num_ue; ++i) + g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); + } else { + /* else, just start with the next UE next time */ + g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); + } + + return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); +} + +void ulsch_scheduler_pre_processor(module_id_t Mod_id, + int CC_id, int frameP, sub_frame_t subframeP, int sched_frameP, - unsigned char sched_subframeP, - uint16_t *first_rb) { - int UE_id; - uint16_t n; - uint8_t CC_id, harq_pid; - uint16_t nb_allocated_rbs[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint16_t total_allocated_rbs[NFAPI_CC_MAX]; - uint16_t average_rbs_per_user[NFAPI_CC_MAX]; - int16_t total_remaining_rbs[NFAPI_CC_MAX]; - uint16_t total_ue_count[NFAPI_CC_MAX]; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - slice_info_t *sli = &eNB->slice_info; - UE_TEMPLATE *UE_template = 0; - UE_sched_ctrl_t *ue_sched_ctl; - int N_RB_UL = 0; - uint16_t available_rbs, first_rb_offset; - rnti_t rntiTable[MAX_MOBILES_PER_ENB]; - // sort ues - LOG_D(MAC, "In ulsch_preprocessor: sort ue \n"); - sort_ue_ul(module_idP, slice_idx, sched_frameP, sched_subframeP, rntiTable); - // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB - LOG_D(MAC, "In ulsch_preprocessor: assign max mcs min rb\n"); - assign_max_mcs_min_rb(module_idP, slice_idx, frameP, subframeP, first_rb); - // we need to distribute RBs among UEs - // step1: reset the vars - uint8_t CC_nb = (uint8_t) RC.nb_mac_CC[module_idP]; + unsigned char sched_subframeP) { + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + const int N_RB_UL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].ul_Bandwidth); + COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; - for (CC_id = 0; CC_id < CC_nb; CC_id++) { - total_allocated_rbs[CC_id] = 0; - total_remaining_rbs[CC_id] = 0; - average_rbs_per_user[CC_id] = 0; - total_ue_count[CC_id] = 0; + UE_list_t UE_to_sched; + UE_to_sched.head = -1; + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + UE_to_sched.next[i] = -1; + + int last_UE_id = -1; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + /* initialize per-UE scheduling information */ + UE_template->pre_assigned_mcs_ul = 0; + UE_template->pre_allocated_nb_rb_ul = 0; + UE_template->pre_allocated_rb_table_index_ul = -1; + UE_template->pre_first_nb_rb_ul = 0; + UE_template->pre_dci_ul_pdu_idx = -1; + + const rnti_t rnti = UE_RNTI(Mod_id, UE_id); + if (rnti == NOT_A_RNTI) { + LOG_E(MAC, "UE %d has RNTI NOT_A_RNTI!\n", UE_id); + continue; + } + if (ue_sched_ctrl->cdrx_configured && !ue_sched_ctrl->in_active_time) + continue; + if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0) + continue; + + /* define UEs to schedule */ + if (UE_to_sched.head < 0) + UE_to_sched.head = UE_id; + else + UE_to_sched.next[last_UE_id] = UE_id; + UE_to_sched.next[UE_id] = -1; + last_UE_id = UE_id; } - // Step 1.5: Calculate total_ue_count - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - // This is not the actual CC_id in the list - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template = &UE_list->UE_template[CC_id][UE_id]; + if (UE_to_sched.head < 0) + return; - if (UE_template->pre_allocated_nb_rb_ul[slice_idx] > 0) { - total_ue_count[CC_id]++; - } + int last_rb_blocked = 1; + int n_contig = 0; + contig_rbs_t rbs[2]; // up to two contig RBs for PRACH in between + for (int i = 0; i < N_RB_UL; ++i) { + if (cc->vrb_map_UL[i] == 0 && last_rb_blocked == 1) { + last_rb_blocked = 0; + n_contig++; + AssertFatal(n_contig <= 2, "cannot handle more than two contiguous RB regions\n"); + rbs[n_contig - 1].start = i; + } + if (cc->vrb_map_UL[i] == 1 && last_rb_blocked == 0) { + last_rb_blocked = 1; + rbs[n_contig - 1].length = i - rbs[n_contig - 1].start; } } - // step 2: calculate the average rb per UE - LOG_D(MAC, "In ulsch_preprocessor: step2 \n"); + round_robin_ul(Mod_id, + CC_id, + frameP, + subframeP, + sched_frameP, + sched_subframeP, + &UE_to_sched, + 4, // max_num_ue + n_contig, + rbs); - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - if (UE_list->UE_template[CC_id][UE_id].rach_resource_type > 0) continue; + // the following block is meant for validation of the pre-processor to check + // whether all UE allocations are non-overlapping and is not necessary for + // scheduling functionality +#ifdef DEBUG_eNB_SCHEDULER + char t[101] = "__________________________________________________" + "__________________________________________________"; + t[N_RB_UL] = 0; + for (int j = 0; j < N_RB_UL; j++) + if (cc->vrb_map_UL[j] != 0) + t[j] = 'x'; + int print = 0; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + if (UE_template->pre_allocated_nb_rb_ul == 0) + continue; - LOG_D(MAC, "In ulsch_preprocessor: handling UE %d/%x\n", + print = 1; + uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id], + sched_frameP, sched_subframeP); + LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n", + frameP, + subframeP, UE_id, - rntiTable[UE_id]); + UE_template->pre_allocated_nb_rb_ul, + UE_template->pre_allocated_rb_table_index_ul, + UE_template->pre_first_nb_rb_ul, + UE_template->pre_assigned_mcs_ul, + UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0 ? "(retx)" : ""); - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - LOG_D(MAC, "In ulsch_preprocessor: handling UE %d/%x CCid %d\n", - UE_id, - rntiTable[UE_id], - CC_id); - /* - if((mac_xface->get_nCCE_max(module_idP,CC_id,3,subframeP) - nCCE_to_be_used[CC_id]) > (1<common_channels[CC_id].ul_Bandwidth); - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx] = - nb_rbs_allowed_slice(sli->ul[slice_idx].pct, N_RB_UL); - first_rb_offset = UE_list->first_rb_offset[CC_id][slice_idx]; - available_rbs = - cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); + for (int i = 0; i < UE_template->pre_allocated_nb_rb_ul; ++i) { + /* only check if this is not a retransmission */ + if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] == 0 + && cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] == 1) { - if (available_rbs < 0) - available_rbs = 0; - - if (total_ue_count[CC_id] == 0) { - average_rbs_per_user[CC_id] = 0; - } else if (total_ue_count[CC_id] == 1) { // increase the available RBs, special case, - average_rbs_per_user[CC_id] = (uint16_t) (available_rbs + 1); - } else if (total_ue_count[CC_id] <= available_rbs) { - average_rbs_per_user[CC_id] = (uint16_t) floor(available_rbs / total_ue_count[CC_id]); - } else { - average_rbs_per_user[CC_id] = 1; - LOG_W(MAC, "[eNB %d] frame %d subframe %d: UE %d CC %d: can't get average rb per user (should not be here)\n", - module_idP, - frameP, - subframeP, - UE_id, - CC_id); - } - - if (total_ue_count[CC_id] > 0) { - LOG_D(MAC, "[eNB %d] Frame %d subframe %d: total ue to be scheduled %d\n", - module_idP, - frameP, - subframeP, - total_ue_count[CC_id]); + LOG_I(MAC, "%4d.%d UL scheduler allocation list: %s\n", frameP, subframeP, t); + LOG_E(MAC, + "%4d.%d: UE %d allocated at locked RB %d (is: allocated start " + "%d/length %d)\n", + frameP, subframeP, UE_id, UE_template->pre_first_nb_rb_ul + i, + UE_template->pre_first_nb_rb_ul, + UE_template->pre_allocated_nb_rb_ul); } + cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] = 1; + t[UE_template->pre_first_nb_rb_ul + i] = UE_id + '0'; } } - - // step 3: assigne RBS - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - // if (continueTable[UE_id]) continue; - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template = &UE_list->UE_template[CC_id][UE_id]; - harq_pid = subframe2harqpid(&RC.mac[module_idP]->common_channels[CC_id], - sched_frameP, sched_subframeP); - - // mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL); - - if (UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) { - nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; - } else { - nb_allocated_rbs[CC_id][UE_id] = - cmin(UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[slice_idx], average_rbs_per_user[CC_id]); - } - - total_allocated_rbs[CC_id] += nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d\n", - nb_allocated_rbs[CC_id][UE_id], - UE_id, - rntiTable[UE_id], - CC_id, - harq_pid); - } - } - - // step 4: assigne the remaining RBs and set the pre_allocated rbs accordingly - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - // if (continueTable[UE_id]) continue; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template = &UE_list->UE_template[CC_id][UE_id]; - N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - first_rb_offset = UE_list->first_rb_offset[CC_id][slice_idx]; - available_rbs = cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); - total_remaining_rbs[CC_id] = available_rbs - total_allocated_rbs[CC_id]; - - if (total_ue_count[CC_id] == 1) { - total_remaining_rbs[CC_id]++; - } - - while (UE_template->pre_allocated_nb_rb_ul[slice_idx] > 0 && - nb_allocated_rbs[CC_id][UE_id] < UE_template->pre_allocated_nb_rb_ul[slice_idx] && - total_remaining_rbs[CC_id] > 0) { - nb_allocated_rbs[CC_id][UE_id] = cmin(nb_allocated_rbs[CC_id][UE_id] + 1, UE_template->pre_allocated_nb_rb_ul[slice_idx]); - total_remaining_rbs[CC_id]--; - total_allocated_rbs[CC_id]++; - } - - UE_template->pre_allocated_nb_rb_ul[slice_idx] = nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC, "******************UL Scheduling Information for UE%d CC_id %d ************************\n", - UE_id, - CC_id); - LOG_D(MAC, "[eNB %d] total RB allocated for UE%d CC_id %d = %d\n", - module_idP, - UE_id, - CC_id, - UE_template->pre_allocated_nb_rb_ul[slice_idx]); - } - } - - return; -} - -void -assign_max_mcs_min_rb(module_id_t module_idP, - int slice_idx, - int frameP, - sub_frame_t subframeP, - uint16_t *first_rb) { - int i; - uint16_t n, UE_id; - uint8_t CC_id; - int mcs; - int rb_table_index = 0, tbs, tx_power; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - slice_info_t *sli = &eNB->slice_info; - UE_TEMPLATE *UE_template; - UE_sched_ctrl_t *ue_sched_ctl; - int Ncp; - int N_RB_UL; - int first_rb_offset, available_rbs; - - for (i = UE_list->head_ul; i >= 0; i = UE_list->next_ul[i]) { - if (UE_list->UE_sched_ctrl[i].phr_received == 1) { - /* if we've received the power headroom information the UE, we can go to - * maximum mcs */ - mcs = cmin(20, sli->ul[slice_idx].maxmcs); - } else { - /* otherwise, limit to QPSK PUSCH */ - mcs = cmin(10, sli->ul[slice_idx].maxmcs); - } - - UE_id = i; - - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - AssertFatal(CC_id < RC.nb_mac_CC[module_idP], "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u", - CC_id, - NFAPI_CC_MAX, - n, - UE_id, - UE_list->numactiveULCCs[UE_id]); - UE_template = &UE_list->UE_template[CC_id][UE_id]; - UE_template->pre_assigned_mcs_ul = mcs; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - Ncp = eNB->common_channels[CC_id].Ncp; - N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx] = nb_rbs_allowed_slice(sli->ul[slice_idx].pct, N_RB_UL); - int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes; - - if (bytes_to_schedule < 0) bytes_to_schedule = 0; - - int bits_to_schedule = bytes_to_schedule * 8; - - // if this UE has UL traffic - if (bits_to_schedule > 0) { - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, 3) << 3; // 1 or 2 PRB with cqi enabled does not work well! - rb_table_index = 2; - // fixme: set use_srs flag - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); - - while ((UE_template->phr_info - tx_power < 0 || tbs > bits_to_schedule) && UE_template->pre_assigned_mcs_ul > 3) { - // LOG_I(MAC,"UE_template->phr_info %d tx_power %d mcs %d\n", UE_template->phr_info,tx_power, mcs); - UE_template->pre_assigned_mcs_ul--; - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); // fixme: set use_srs - } - - first_rb_offset = UE_list->first_rb_offset[CC_id][slice_idx]; - available_rbs = - cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); - - while (tbs < bits_to_schedule && - rb_table[rb_table_index] < available_rbs && - UE_template->phr_info - tx_power > 0 && - rb_table_index < 32) { - rb_table_index++; - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); - } - - if (rb_table[rb_table_index] > (available_rbs - 1)) { - rb_table_index--; - } - - // 1 or 2 PRB with cqi enabled does not work well - if (rb_table[rb_table_index] < 3) { - rb_table_index = 2; //3PRB - } - - UE_template->pre_allocated_rb_table_index_ul = rb_table_index; - UE_template->pre_allocated_nb_rb_ul[slice_idx] = rb_table[rb_table_index]; - LOG_D(MAC, "[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n", - module_idP, - frameP, - subframeP, - UE_id, - CC_id, - UE_template->pre_assigned_mcs_ul, - UE_template->pre_allocated_rb_table_index_ul, - UE_template->pre_allocated_nb_rb_ul[slice_idx], - UE_template->phr_info, tx_power); - } else { - /* if UE has pending scheduling request then pre-allocate 3 RBs */ - //if (UE_template->ul_active == 1 && UE_template->ul_SR == 1) { - if (UE_is_to_be_scheduled(module_idP, CC_id, i)) { - /* use QPSK mcs */ - UE_template->pre_assigned_mcs_ul = 10; - UE_template->pre_allocated_rb_table_index_ul = 2; - UE_template->pre_allocated_nb_rb_ul[slice_idx] = 3; - } else { - UE_template->pre_assigned_mcs_ul = 0; - UE_template->pre_allocated_rb_table_index_ul = -1; - UE_template->pre_allocated_nb_rb_ul[slice_idx] = 0; - } - } - } - } -} - -struct sort_ue_ul_params { - int module_idP; - int sched_frameP; - int sched_subframeP; -}; - -static int ue_ul_compare(const void *_a, const void *_b, void *_params) { - struct sort_ue_ul_params *params = _params; - UE_list_t *UE_list = &RC.mac[params->module_idP]->UE_list; - int UE_id1 = *(const int *) _a; - int UE_id2 = *(const int *) _b; - int rnti1 = UE_RNTI(params->module_idP, UE_id1); - int pCCid1 = UE_PCCID(params->module_idP, UE_id1); - int round1 = maxround_ul(params->module_idP, rnti1, params->sched_frameP, - params->sched_subframeP); - int rnti2 = UE_RNTI(params->module_idP, UE_id2); - int pCCid2 = UE_PCCID(params->module_idP, UE_id2); - int round2 = maxround_ul(params->module_idP, rnti2, params->sched_frameP, - params->sched_subframeP); - - if (round1 > round2) - return -1; - - if (round1 < round2) - return 1; - - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] > - UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) - return -1; - - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < - UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) - return 1; - - int bytes_to_schedule1 = UE_list->UE_template[pCCid1][UE_id1].estimated_ul_buffer - UE_list->UE_template[pCCid1][UE_id1].scheduled_ul_bytes; - - if (bytes_to_schedule1 < 0) bytes_to_schedule1 = 0; - - int bytes_to_schedule2 = UE_list->UE_template[pCCid2][UE_id2].estimated_ul_buffer - UE_list->UE_template[pCCid2][UE_id2].scheduled_ul_bytes; - - if (bytes_to_schedule2 < 0) bytes_to_schedule2 = 0; - - if (bytes_to_schedule1 > bytes_to_schedule2) - return -1; - - if (bytes_to_schedule1 < bytes_to_schedule2) - return 1; - - if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul > - UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) - return -1; - - if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < - UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) - return 1; - - if (UE_list->UE_sched_ctrl[UE_id1].cqi_req_timer > - UE_list->UE_sched_ctrl[UE_id2].cqi_req_timer) - return -1; - - if (UE_list->UE_sched_ctrl[UE_id1].cqi_req_timer < - UE_list->UE_sched_ctrl[UE_id2].cqi_req_timer) - return 1; - - return 0; -} - -//----------------------------------------------------------------------------- -/* - * This function sorts the UEs in order, depending on their ulsch buffer and CQI - */ -void sort_ue_ul(module_id_t module_idP, - int slice_idx, - int sched_frameP, - sub_frame_t sched_subframeP, - rnti_t *rntiTable) -//----------------------------------------------------------------------------- -{ - int list[MAX_MOBILES_PER_ENB]; - int list_size = 0; - struct sort_ue_ul_params params = { module_idP, sched_frameP, sched_subframeP }; - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; - UE_sched_ctrl_t *UE_scheduling_control = NULL; - - for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) { - UE_scheduling_control = &(UE_list->UE_sched_ctrl[i]); - - /* Check CDRX configuration and if UE is in active time for this subframe */ - if (UE_scheduling_control->cdrx_configured == TRUE) { - if (UE_scheduling_control->in_active_time == FALSE) { - continue; - } - } - - rntiTable[i] = UE_RNTI(module_idP, i); - - // Valid element and is not the actual CC_id in the list - if (UE_list->active[i] == TRUE && - rntiTable[i] != NOT_A_RNTI && - UE_list->UE_sched_ctrl[i].ul_out_of_sync != 1 && - ue_ul_slice_membership(module_idP, i, slice_idx)) { - list[list_size++] = i; // Add to list - } - } - - qsort_r(list, list_size, sizeof(int), ue_ul_compare, ¶ms); - - if (list_size) { // At mimimum one list element - for (int i = 0; i < list_size - 1; i++) { - UE_list->next_ul[list[i]] = list[i + 1]; - } - - UE_list->next_ul[list[list_size - 1]] = -1; - UE_list->head_ul = list[0]; - } else { // No element - UE_list->head_ul = -1; - } + if (print) + LOG_D(MAC, + "%4d.%d UL scheduler allocation list: %s\n", + sched_frameP, + sched_subframeP, + t); +#endif } diff --git a/openair2/LAYER2/MAC/ra_procedures.c b/openair2/LAYER2/MAC/ra_procedures.c index 19b1c7708b..0d1afdf2a2 100644 --- a/openair2/LAYER2/MAC/ra_procedures.c +++ b/openair2/LAYER2/MAC/ra_procedures.c @@ -390,7 +390,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id, LOG_USEDINLOG_VAR(mac_rlc_status_resp_t,rlc_status)=mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP, subframeP, - ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6,0, 0 + ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 0, 0 ); if (UE_mac_inst[module_idP].crnti_before_ho) @@ -406,7 +406,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id, module_idP, frameP, rlc_status.bytes_in_buffer, dcch_header_len); - sdu_lengths = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP, ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6, //not used + sdu_lengths = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP, ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6, (char *) &ulsch_buff[0],0, 0 ); diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index 1205851915..24630c0fe2 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -1972,6 +1972,10 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, subframe, ENB_FLAG_NO, lcid); lcid_buffer_occupancy_new = lcid_buffer_occupancy_old; +#if 0 + /* TODO: those assert crash the L2 simulator with the new RLC. + * Are they necessary? + */ AssertFatal(lcid_buffer_occupancy_new == UE_mac_inst[module_idP]. scheduling_info.LCID_buffer_remain[lcid], @@ -1990,6 +1994,7 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, scheduling_info.BSR_bytes[UE_mac_inst[module_idP]. scheduling_info.LCGID [lcid]]); +#endif //Multiplex all available DCCH RLC PDUs considering to multiplex the last PDU each time for maximize the data //Adjust at the end of the loop @@ -2085,18 +2090,10 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, } //Update Buffer remain and BSR bytes after transmission - AssertFatal(lcid_buffer_occupancy_new <= - lcid_buffer_occupancy_old, - "MAC UE Tx error : Buffer Occupancy After Tx=%d greater than before=%d BO! for LCID=%d RLC PDU nb=%d Frame %d Subrame %d\n", - lcid_buffer_occupancy_new, - lcid_buffer_occupancy_old, lcid, - lcid_rlc_pdu_count, frameP, subframe); - UE_mac_inst[module_idP].scheduling_info. - LCID_buffer_remain[lcid] = lcid_buffer_occupancy_new; - UE_mac_inst[module_idP]. - scheduling_info.BSR_bytes[UE_mac_inst[module_idP]. - scheduling_info.LCGID[lcid]] += - (lcid_buffer_occupancy_new - lcid_buffer_occupancy_old); + UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = lcid_buffer_occupancy_new; + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] += (lcid_buffer_occupancy_new - lcid_buffer_occupancy_old); + if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] < 0) + UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] = 0; //Update the number of LCGID with data as BSR shall reflect status after BSR transmission if ((num_lcg_id_with_data > 1) @@ -2809,7 +2806,6 @@ update_bsr(module_id_t module_idP, frame_t frameP, rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO, lcid, - 0xFFFF, //TBS is not used in RLC at this step, set a special value for debug 0, 0 ); lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer; @@ -3176,7 +3172,7 @@ SLSCH_t *ue_get_slsch(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_ for (int j = 0; j < ue->numCommFlows; j++) { if ((ue->sourceL2Id > 0) && (ue->destinationList[j] >0) ) { rlc_status = mac_rlc_status_ind(module_idP, 0x1234,0,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO, - ue->SL_LCID[i], 0xFFFF, ue->sourceL2Id, ue->destinationList[j]); + ue->SL_LCID[i], ue->sourceL2Id, ue->destinationList[j]); if (rlc_status.bytes_in_buffer > 2) { LOG_I(MAC,"SFN.SF %d.%d: Scheduling for %d bytes in Sidelink buffer\n",frameP,subframeP,rlc_status.bytes_in_buffer); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index d41c34836d..38083c4836 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -178,6 +178,11 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *nr_pdci_info_extracted); +uint8_t +nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) ; + int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu, int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSlots, int nrofUplinkSymbols); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 8be234bf02..1f730b8248 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -478,7 +478,6 @@ int8_t nr_ue_decode_mib(module_id_t module_id, uint32_t number_of_search_space_per_slot=UINT_MAX; uint32_t first_symbol_index=UINT_MAX; uint32_t search_space_duration; // element of search space - uint32_t coreset_duration; // element of coreset // 38.213 table 10.1-1 /// MUX PATTERN 1 @@ -614,8 +613,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, } AssertFatal(number_of_search_space_per_slot!=UINT_MAX,""); - coreset_duration = num_symbols * number_of_search_space_per_slot; /* + uint32_t coreset_duration = num_symbols * number_of_search_space_per_slot; mac->type0_pdcch_dci_config.number_of_candidates[0] = table_38213_10_1_1_c2[0]; mac->type0_pdcch_dci_config.number_of_candidates[1] = table_38213_10_1_1_c2[1]; mac->type0_pdcch_dci_config.number_of_candidates[2] = table_38213_10_1_1_c2[2]; // CCE aggregation level = 4 diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 218c7acbe6..965e42b523 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -598,7 +598,6 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, 0, 0); @@ -615,7 +614,7 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS_bytes, + TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, (char *)&mac_sdus[sdu_length_total], 0, 0); diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent.c b/openair2/LAYER2/PROTO_AGENT/proto_agent.c index bead6ad28d..6bf9cdce22 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * 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 enb_agent.h * \brief top level enb agent receive thread and itti task diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent.h b/openair2/LAYER2/PROTO_AGENT/proto_agent.h index 927b714b2c..6898c9e447 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent.h @@ -1,32 +1,23 @@ - -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * 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 proto_agent.h * \brief top level protocol agent diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c index eef697c5bb..df3684ee27 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c @@ -1,32 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ - +/* + * 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 "proto_agent_async.h" #include "proto_agent_defs.h" diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h index 27030924cd..6bc952e804 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * 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 enb_agent_async.h * \brief channel implementation for async interface diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c index a11c029bd3..6e343343cd 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * 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 proto_agent_common.c * \brief common primitives for all agents diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h index 70e6b2a84e..c805b81543 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * 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 enb_agent_common.h * \brief common message primitves and utilities diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h index 08c91e7085..cd730a6de8 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2016 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * 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 enb_agent_defs.h * \brief enb agent common definitions diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_handler.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_handler.c index cb65da2803..82f7849717 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_handler.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_handler.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * 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 enb_agent_handler.c * \brief enb agent tx and rx message handler diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c index f64a58f8e1..9a63427ed5 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2016 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * 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 enb_agent_net_comm.c * \brief enb agent network interface abstraction diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h index c956bf48b1..55fca5a928 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2016 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * 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 enb_agent_net_comm.h * \brief enb agent network interface abstraction diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c index 865a815359..de947225bb 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c @@ -459,7 +459,6 @@ struct mac_status_resp rlc_am_mac_status_indication ( const protocol_ctxt_t *const ctxt_pP, void *const rlc_pP, - const uint16_t tb_sizeP, struct mac_status_ind tx_statusP, const eNB_flag_t enb_flagP) { struct mac_status_resp status_resp; @@ -491,10 +490,6 @@ rlc_am_mac_status_indication ( rlc->last_absolute_subframe_status_indication = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP); - if (tb_sizeP > 0) { - rlc->nb_bytes_requested_by_mac = tb_sizeP; - } - status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, rlc); // For eNB scheduler : Add Max RLC header size for new PDU @@ -549,8 +544,7 @@ rlc_am_mac_status_indication ( NULL,0, MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" STATUS-IND %u", MSC_AS_TIME_ARGS(ctxt_pP), - PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc), - tb_sizeP); + PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc)); MSC_LOG_TX_MESSAGE( (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE, (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_MAC_ENB:MSC_MAC_UE, @@ -565,26 +559,14 @@ rlc_am_mac_status_indication ( } if (LOG_DEBUGFLAG(DEBUG_RLC)) { - if (tb_sizeP > 0) { - LOG_UI(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc), - tb_sizeP, - status_resp.buffer_occupancy_in_bytes); - } + LOG_UI(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_STATUS_INDICATION (DATA) -> %d bytes\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc), + status_resp.buffer_occupancy_in_bytes); } return status_resp; } -//----------------------------------------------------------------------------- -void -rlc_am_set_nb_bytes_requested_by_mac ( - void *const rlc_pP, - const tb_size_t tb_sizeP -) { - ((rlc_am_entity_t *) rlc_pP)->nb_bytes_requested_by_mac = tb_sizeP; -} - //----------------------------------------------------------------------------- struct mac_data_req rlc_am_mac_data_request ( diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h index f2cb456e8c..3127f67eca 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h @@ -255,23 +255,15 @@ rlc_am_get_pdus ( */ void rlc_am_rx (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind); -/*! \fn struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) +/*! \fn struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) * \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission. * \param[in] ctxt_pP Running context. * \param[in] rlc_pP RLC AM protocol instance pointer. -* \param[in] tbs_sizeP Number of bytes requested by MAC for next transmission. * \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU. * \param[in] enb_flagP eNB or UE flag indication. * \return The maximum number of bytes that can be served by RLC instance to MAC. */ -struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP); - -/*! \fn void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP) -* \brief Set available TBS for RLC Tx just before am_mac_data_request. Used for UE only. -* \param[in] rlc_pP RLC AM protocol instance pointer. -* \param[in] tb_sizeP Available Tx Transport Block size in bytes. -*/ -void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP); +struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP); /*! \fn struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP,const eNB_flag_t enb_flagP) * \brief Gives PDUs to lower layer MAC. diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c index e481550a46..4e3fffe176 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c @@ -151,13 +151,10 @@ struct mac_status_resp rlc_tm_mac_status_indication ( const protocol_ctxt_t* const ctxt_pP, void * const rlc_pP, - const tb_size_t tb_sizeP, struct mac_status_ind tx_statusP) { struct mac_status_resp status_resp; - ((rlc_tm_entity_t *) rlc_pP)->rlc_pdu_size = tb_sizeP; - status_resp.buffer_occupancy_in_bytes = ((rlc_tm_entity_t *) rlc_pP)->buffer_occupancy; status_resp.buffer_occupancy_in_pdus = status_resp.buffer_occupancy_in_bytes / ((rlc_tm_entity_t *) rlc_pP)->rlc_pdu_size; status_resp.rlc_info.rlc_protocol_state = ((rlc_tm_entity_t *) rlc_pP)->protocol_state; diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h index 1ea9988707..d2bab33b1a 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h @@ -88,11 +88,10 @@ void rlc_tm_rx ( struct mac_data_ind data_indP); -/*! \fn struct mac_status_resp rlc_tm_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void * const rlcP, const uint16_t tbs_sizeP, struct mac_status_ind tx_statusP) +/*! \fn struct mac_status_resp rlc_tm_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void * const rlcP, struct mac_status_ind tx_statusP) * \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission. * \param[in] ctxtP Running context. * \param[in] rlcP RLC TM protocol instance pointer. -* \param[in] tbs_sizeP Number of bytes requested by MAC for next transmission. * \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU. * \return The maximum number of bytes that can be served by RLC instance to MAC. */ @@ -100,7 +99,6 @@ struct mac_status_resp rlc_tm_mac_status_indication ( const protocol_ctxt_t* const ctxt_pP, void * const rlc_pP, - const tb_size_t tb_sizeP, struct mac_status_ind tx_statusP); diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c index c7dc11f51d..654ddb8da7 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c @@ -370,7 +370,7 @@ rlc_um_rx (const protocol_ctxt_t *const ctxt_pP, void *argP, struct mac_data_ind //----------------------------------------------------------------------------- struct mac_status_resp -rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) { +rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) { struct mac_status_resp status_resp; uint16_t sdu_size = 0; uint16_t sdu_remaining_size = 0; @@ -386,7 +386,6 @@ rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP if (rlc_pP) { status_resp.rlc_info.rlc_protocol_state = rlc_p->protocol_state; rlc_um_check_timer_dar_time_out(ctxt_pP, rlc_p); - rlc_p->nb_bytes_requested_by_mac = tbs_sizeP; status_resp.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (rlc_p); if ((status_resp.buffer_occupancy_in_bytes > 0) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) { @@ -416,9 +415,8 @@ rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP if (LOG_DEBUGFLAG(DEBUG_RLC)) { if (( rlc_p->rb_id > 0) && (status_resp.buffer_occupancy_in_bytes > 0)) { - LOG_UI(RLC, PROTOCOL_RLC_UM_CTXT_FMT"MAC_STATUS_INDICATION (DATA) %d bytes requested -> %d bytes available\n", + LOG_UI(RLC, PROTOCOL_RLC_UM_CTXT_FMT"MAC_STATUS_INDICATION (DATA) -> %d bytes available\n", PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p), - tbs_sizeP, status_resp.buffer_occupancy_in_bytes); if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) { @@ -441,15 +439,6 @@ rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP return status_resp; } -//----------------------------------------------------------------------------- -void -rlc_um_set_nb_bytes_requested_by_mac ( - void *rlc_pP, - const tb_size_t tb_sizeP -) { - ((rlc_um_entity_t *) rlc_pP)->nb_bytes_requested_by_mac = tb_sizeP; -} - //----------------------------------------------------------------------------- struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP,const eNB_flag_t enb_flagP) { diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h index 8000196b32..be06551dde 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h @@ -160,27 +160,15 @@ rlc_um_get_pdus (const protocol_ctxt_t* const ctxt_pP, void *argP); */ void rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, void *argP, struct mac_data_ind data_indP); -/*! \fn struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP) +/*! \fn struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, struct mac_status_ind tx_statusP) * \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission. * \param[in] ctxt_pP Running context. * \param[in] rlc_pP RLC UM protocol instance pointer. -* \param[in] tbs_sizeP Number of bytes requested by MAC for next transmission. * \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU. * \return The maximum number of bytes that can be served by RLC instance to MAC. */ struct mac_status_resp -rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP); - -/*! \fn void rlc_um_set_nb_bytes_requested_by_mac (rlc_um_entity_t * const rlc_pP, const tb_size_t tb_sizeP) -* \brief Set available TBS size for MAC Tx. -* \param[in] rlc_pP RLC UM protocol instance pointer. -* \param[in] tb_sizeP remaining TBS in bytes. -*/ -void -rlc_um_set_nb_bytes_requested_by_mac ( - void * rlc_pP, - const tb_size_t tb_sizeP -); +rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP); /*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,const eNB_flag_t enb_flagP) * \brief Gives PDUs to lower layer MAC. diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h index dfdf527123..27ca18ed7e 100644 --- a/openair2/LAYER2/RLC/rlc.h +++ b/openair2/LAYER2/RLC/rlc.h @@ -137,7 +137,7 @@ void (*rlc_rrc_data_ind)( const protocol_ctxt_t *const ctxtP, const rb_id_t rb_idP, const sdu_size_t sdu_sizeP, - const uint8_t *const sduP); + const uint8_t *const sduP) __attribute__ ((aligned(32))); void (*rlc_rrc_data_conf)( const protocol_ctxt_t *const ctxtP, @@ -250,7 +250,7 @@ logical_chan_id_t rlc_mbms_rbid2lcid_eNB[MAX_eNB][NB_RB_MBMS_MAX]; (((hash_key_t)(sESSION_ID)) << 37) | \ (((hash_key_t)(0x0000000000000001)) << 63)) -hash_table_t *rlc_coll_p; +hash_table_t *rlc_coll_p __attribute__ ((aligned(32))); /*! \fn tbs_size_t mac_rlc_serialize_tb (char* bufferP, list_t transport_blocksP) * \brief Serialize a list of transport blocks coming from RLC in order to be processed by MAC. @@ -391,7 +391,7 @@ void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t r * \param [in] eNB_flagP Flag to indicate eNB (1) or UE (0) * \param [in] MBMS_flagP Flag to indicate whether this is the MBMS service (1) or not (0) * \param [in] rb_idP Radio bearer identifier. -* \param [in] tb_sizeP Available Tx TBS in bytes. For UE only. +* \param [in] tb_sizeP Requested Tx TBS in bytes. * \param [in,out] bufferP Memory area to fill with the bytes requested by MAC. * \return A status about the processing, OK or error code. */ @@ -416,7 +416,7 @@ tbs_size_t mac_rlc_data_req (const module_id_t, const rnti_t, con void mac_rlc_data_ind (const module_id_t, const rnti_t, const eNB_index_t,const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, char *, tb_size_t, num_tb_t, crc_t * ); -/*! \fn mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const sub_frame_t subframeP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP, tb_size_t tb_sizeP) +/*! \fn mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const sub_frame_t subframeP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP) * \brief Interface with MAC layer, request and set the number of bytes scheduled for transmission by the RLC instance corresponding to the radio bearer identifier. * \param[in] mod_idP Virtualized module identifier. * \param[in] rntiP UE identifier. @@ -425,10 +425,9 @@ void mac_rlc_data_ind (const module_id_t, const rnti_t, con * \param[in] eNB_flagP Flag to indicate eNB operation (1 true, 0 false) * \param[in] MBMS_flagP Flag to indicate whether this is the MBMS service (1) or not (0) * \param[in] rb_idP Radio bearer identifier. -* \param[in] tb_sizeP Size of a transport block set in bytes. * \return The maximum number of bytes that the RLC instance can send in the next transmission sequence. */ -mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, tb_size_t +mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t ,const uint32_t sourceL2Id ,const uint32_t destinationL2Id ); diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c index 9cf6cb739a..89cbe4c406 100644 --- a/openair2/LAYER2/RLC/rlc_mac.c +++ b/openair2/LAYER2/RLC/rlc_mac.c @@ -191,20 +191,19 @@ tbs_size_t mac_rlc_data_req( case RLC_MODE_AM: rlc_am_mui.rrc_mui_num = 0; - if (!enb_flagP) rlc_am_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.am,tb_sizeP); - + ((rlc_am_entity_t *) &rlc_union_p->rlc.am)->nb_bytes_requested_by_mac = tb_sizeP; data_request = rlc_am_mac_data_request(&ctxt, &rlc_union_p->rlc.am,enb_flagP); ret_tb_size =mac_rlc_serialize_tb(buffer_pP, data_request.data); break; case RLC_MODE_UM: - if (!enb_flagP) rlc_um_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.um,tb_sizeP); - + ((rlc_um_entity_t *) &rlc_union_p->rlc.um)->nb_bytes_requested_by_mac = tb_sizeP; data_request = rlc_um_mac_data_request(&ctxt, &rlc_union_p->rlc.um,enb_flagP); ret_tb_size = mac_rlc_serialize_tb(buffer_pP, data_request.data); break; case RLC_MODE_TM: + ((rlc_tm_entity_t *) &rlc_union_p->rlc.tm)->rlc_pdu_size = tb_sizeP; data_request = rlc_tm_mac_data_request(&ctxt, &rlc_union_p->rlc.tm); ret_tb_size = mac_rlc_serialize_tb(buffer_pP, data_request.data); break; @@ -317,7 +316,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( const eNB_flag_t enb_flagP, const MBMS_flag_t MBMS_flagP, const logical_chan_id_t channel_idP, - const tb_size_t tb_sizeP, const uint32_t sourceL2Id, const uint32_t destinationL2Id ) { @@ -370,7 +368,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( break; case RLC_MODE_AM: - status_resp = rlc_am_mac_status_indication(&ctxt, &rlc_union_p->rlc.am, tb_sizeP, tx_status,enb_flagP); + status_resp = rlc_am_mac_status_indication(&ctxt, &rlc_union_p->rlc.am, tx_status,enb_flagP); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.head_sdu_creation_time = status_resp.head_sdu_creation_time; mac_rlc_status_resp.head_sdu_remaining_size_to_send = status_resp.head_sdu_remaining_size_to_send; @@ -379,7 +377,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( break; case RLC_MODE_UM: - status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tb_sizeP, tx_status, enb_flagP); + status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tx_status, enb_flagP); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus; mac_rlc_status_resp.head_sdu_creation_time = status_resp.head_sdu_creation_time; @@ -389,7 +387,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( break; case RLC_MODE_TM: - status_resp = rlc_tm_mac_status_indication(&ctxt, &rlc_union_p->rlc.tm, tb_sizeP, tx_status); + status_resp = rlc_tm_mac_status_indication(&ctxt, &rlc_union_p->rlc.tm, tx_status); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus; // return mac_rlc_status_resp; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 88bde65107..ff0d446e3f 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -107,7 +107,6 @@ tbs_size_t mac_rlc_data_req( int ret; nr_rlc_ue_t *ue; nr_rlc_entity_t *rb; - int is_enb; int maxsize; nr_rlc_manager_lock(nr_rlc_ue_manager); @@ -121,12 +120,7 @@ tbs_size_t mac_rlc_data_req( if (rb != NULL) { rb->set_time(rb, nr_rlc_current_time); - /* UE does not seem to use saved_status_ind_tb_size */ - is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager); - if (is_enb) - maxsize = ue->saved_status_ind_tb_size[channel_idP - 1]; - else - maxsize = tb_sizeP; + maxsize = tb_sizeP; ret = rb->generate_pdu(rb, buffer_pP, maxsize); } else { LOG_E(RLC, "%s:%d:%s: fatal: data req for unknown RB\n", __FILE__, __LINE__, __FUNCTION__); @@ -152,7 +146,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( const eNB_flag_t enb_flagP, const MBMS_flag_t MBMS_flagP, const logical_chan_id_t channel_idP, - const tb_size_t tb_sizeP, const uint32_t sourceL2Id, const uint32_t destinationL2Id ) @@ -189,7 +182,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( ret.bytes_in_buffer = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size; - ue->saved_status_ind_tb_size[channel_idP - 1] = tb_sizeP; } else { ret.bytes_in_buffer = 0; } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h index 97da28cdce..464cf3d083 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h @@ -28,10 +28,6 @@ typedef void nr_rlc_ue_manager_t; typedef struct nr_rlc_ue_t { int rnti; - /* due to openair calling status_ind/data_req, we need to keep this. - * To be considered 'hackish'. - */ - int saved_status_ind_tb_size[2+5]; nr_rlc_entity_t *srb[2]; nr_rlc_entity_t *drb[5]; } nr_rlc_ue_t; diff --git a/openair2/LAYER2/openair2_proc.c b/openair2/LAYER2/openair2_proc.c index 32c4d9788c..bbdc55e036 100644 --- a/openair2/LAYER2/openair2_proc.c +++ b/openair2/LAYER2/openair2_proc.c @@ -91,12 +91,12 @@ int dump_eNB_l2_stats(char *buffer, int length) { number_of_cards=NB_eNB_INST; #endif eNB_MAC_INST *eNB; - UE_list_t *UE_list; + UE_info_t *UE_info; for (eNB_id=0; eNB_idUE_list; + UE_info = &eNB->UE_info; for (CC_id=0 ; CC_id < MAX_NUM_CCs; CC_id++) { eNB->eNB_stats[CC_id].dlsch_bitrate= 0; @@ -141,76 +141,76 @@ int dump_eNB_l2_stats(char *buffer, int length) { len += sprintf(&buffer[len],"\n"); - for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { - for (i=0; inumactiveCCs[UE_id]; i++) { - CC_id=UE_list->ordered_CCids[i][UE_id]; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate=((UE_list->eNB_UE_stats[CC_id][UE_id].TBS*8)/((eNB->frame + 1)*10)); - UE_list->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate= ((UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes*8)/((eNB->frame + 1)*10)); - UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes+= UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes; - UE_list->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes=((UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes*8)/((eNB->frame + 1)*10)); - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate=((UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS*8)/((eNB->frame + 1)*10)); - UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate= ((UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx*8)/((eNB->frame + 1)*10)); + for (UE_id=UE_info->list.head; UE_id>=0; UE_id=UE_info->list.next[UE_id]) { + for (i=0; inumactiveCCs[UE_id]; i++) { + CC_id=UE_info->ordered_CCids[i][UE_id]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate=((UE_info->eNB_UE_stats[CC_id][UE_id].TBS*8)/((eNB->frame + 1)*10)); + UE_info->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate= ((UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes*8)/((eNB->frame + 1)*10)); + UE_info->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes+= UE_info->eNB_UE_stats[CC_id][UE_id].overhead_bytes; + UE_info->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes=((UE_info->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes*8)/((eNB->frame + 1)*10)); + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate=((UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS*8)/((eNB->frame + 1)*10)); + UE_info->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate= ((UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx*8)/((eNB->frame + 1)*10)); len += sprintf(&buffer[len],"[MAC] UE %d (DLSCH),status %s, RNTI %x : CQI %d, MCS1 %d, MCS2 %d, RB (tx %d, retx %d, total %d), ncce (tx %d, retx %d) \n", UE_id, - map_int_to_str(rrc_status_names, UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status), - UE_list->eNB_UE_stats[CC_id][UE_id].crnti, - UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id], - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1, - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2, - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used, - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx, - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used, - UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used, - UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx + map_int_to_str(rrc_status_names, UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status), + UE_info->eNB_UE_stats[CC_id][UE_id].crnti, + UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1, + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2, + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used, + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used_retx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used, + UE_info->eNB_UE_stats[CC_id][UE_id].ncce_used, + UE_info->eNB_UE_stats[CC_id][UE_id].ncce_used_retx ); len += sprintf(&buffer[len], "[MAC] DLSCH bitrate (TTI %d, avg %d), Transmitted bytes " "(TTI %d, total %"PRIu64"), Total Transmitted PDU %d, Overhead " "(TTI %"PRIu64", total %"PRIu64", avg %"PRIu64")\n", - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate, - UE_list->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate, - UE_list->eNB_UE_stats[CC_id][UE_id].TBS, - UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes, - UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus, - UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes, - UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes, - UE_list->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate, + UE_info->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate, + UE_info->eNB_UE_stats[CC_id][UE_id].TBS, + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus, + UE_info->eNB_UE_stats[CC_id][UE_id].overhead_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes ); len += sprintf(&buffer[len],"[MAC] UE %d (ULSCH), Status %s, Failute timer %d, RNTI %x : snr (%d, target %d), MCS (pre %d, post %d), RB (rx %d, retx %d, total %d), Current TBS %d \n", UE_id, - map_int_to_str(rrc_status_names, UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status), - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer, - UE_list->eNB_UE_stats[CC_id][UE_id].crnti, - UE_list->eNB_UE_stats[CC_id][UE_id].snr, - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr, - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1, - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2, - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS + map_int_to_str(rrc_status_names, UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status), + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer, + UE_info->eNB_UE_stats[CC_id][UE_id].crnti, + UE_info->eNB_UE_stats[CC_id][UE_id].snr, + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr, + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1, + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2, + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS ); len += sprintf(&buffer[len], "[MAC] ULSCH bitrate (TTI %d, avg %d), received bytes (total %"PRIu64")," "Total received PDU %d, Total errors %d\n", - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate, - UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate, - UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].num_errors_rx); - len+= sprintf(&buffer[len],"[MAC] Received PHR PH = %d (db)\n", UE_list->UE_template[CC_id][UE_id].phr_info); + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate, + UE_info->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate, + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].num_errors_rx); + len+= sprintf(&buffer[len],"[MAC] Received PHR PH = %d (db)\n", UE_info->UE_template[CC_id][UE_id].phr_info); len+= sprintf(&buffer[len],"[MAC] Estimated size LCGID[0][1][2][3] = %u %u %u %u\n", - UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID0], - UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID1], - UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID2], - UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID3] + UE_info->UE_template[CC_id][UE_id].ul_buffer_info[LCGID0], + UE_info->UE_template[CC_id][UE_id].ul_buffer_info[LCGID1], + UE_info->UE_template[CC_id][UE_id].ul_buffer_info[LCGID2], + UE_info->UE_template[CC_id][UE_id].ul_buffer_info[LCGID3] ); } PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, eNB_id, ENB_FLAG_YES, - UE_list->eNB_UE_stats[0][UE_id].crnti,//UE_PCCID(eNB_id,UE_id)][UE_id].crnti, + UE_info->eNB_UE_stats[0][UE_id].crnti,//UE_PCCID(eNB_id,UE_id)][UE_id].crnti, eNB->frame, eNB->subframe, eNB_id); @@ -509,7 +509,7 @@ int openair2_stats_read(char *buffer, char **my_buffer, off_t off, int length) { for(i=1; i<=NB_CNX_CH; i++) { if (CH_mac_inst[Mod_id].Dcch_lchan[i].Active==1) { len+=sprintf(&buffer[len],"\nMR index %u: DL SINR (feedback) %d dB, CQI: %s\n\n", - i,//CH_rrc_inst[Mod_id].Info.UE_list[i].L2_id[0], + i,//CH_rrc_inst[Mod_id].Info.UE_info[i].L2_id[0], CH_mac_inst[Mod_id].Def_meas[i].Wideband_sinr, print_cqi(CH_mac_inst[Mod_id].Def_meas[i].cqi)); len+=sprintf(&buffer[len], diff --git a/openair2/LAYER2/rlc_v2/TODO b/openair2/LAYER2/rlc_v2/TODO new file mode 100644 index 0000000000..0778d4320b --- /dev/null +++ b/openair2/LAYER2/rlc_v2/TODO @@ -0,0 +1,18 @@ +RLC AM +====== + +- 36.322 5.4 Re-establishment procedure + when possible, reassemble RLC SDUs from any byte segments of AMD PDUs + with SN < VR(MR) in the receiving side, remove RLC headers when doing + so and deliver all reassembled RLC SDUs to upper layer in ascending order + of the RLC SN, if not delivered before; + +- 36.322 5.2.3 Status reporting + delay triggering the STATUS report until x < VR(MS) or x >= VR(MR) + +- 36.322 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception + buffer + [...] and in-sequence byte segments of the AMD PDU with SN = VR(R) [...] + +- use SOstart/SOend in NACK reporting, do not NACK full PDU if + parts of it have been received diff --git a/openair2/LAYER2/rlc_v2/asn1_utils.c b/openair2/LAYER2/rlc_v2/asn1_utils.c new file mode 100644 index 0000000000..46f7d90da5 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/asn1_utils.c @@ -0,0 +1,129 @@ +/* + * 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 "rlc.h" + +int decode_t_reordering(int v) +{ + static int tab[32] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, + 90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 1600 + }; + + if (v < 0 || v > 31) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_t_status_prohibit(int v) +{ + static int tab[62] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, + 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, + 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240, + 245, 250, 300, 350, 400, 450, 500, 800, 1000, 1200, 1600, 2000, 2400 + }; + + if (v < 0 || v > 61) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_t_poll_retransmit(int v) +{ + static int tab[59] = { + 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, + 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, + 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240, 245, + 250, 300, 350, 400, 450, 500, 800, 1000, 2000, 4000 + }; + + if (v < 0 || v > 58) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_poll_pdu(int v) +{ + static int tab[8] = { + 4, 8, 16, 32, 64, 128, 256, -1 /* -1 means infinity */ + }; + + if (v < 0 || v > 7) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_poll_byte(int v) +{ + static int tab[15] = { + 25, 50, 75, 100, 125, 250, 375, 500, 750, 1000, 1250, 1500, 2000, 3000, + -1 /* -1 means infinity */ + }; + + if (v < 0 || v > 14) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (tab[v] == -1) return -1; + return tab[v] * 1024; +} + +int decode_max_retx_threshold(int v) +{ + static int tab[8] = { + 1, 2, 3, 4, 6, 8, 16, 32 + }; + + if (v < 0 || v > 7) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_sn_field_length(int v) +{ + static int tab[2] = { + 5, 10 + }; + + if (v < 0 || v > 1) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} diff --git a/openair2/UTIL/MEM/mem_mngt_proto_extern.h b/openair2/LAYER2/rlc_v2/asn1_utils.h similarity index 77% rename from openair2/UTIL/MEM/mem_mngt_proto_extern.h rename to openair2/LAYER2/rlc_v2/asn1_utils.h index 4690bba42e..61394c9c69 100644 --- a/openair2/UTIL/MEM/mem_mngt_proto_extern.h +++ b/openair2/LAYER2/rlc_v2/asn1_utils.h @@ -19,3 +19,15 @@ * contact@openairinterface.org */ +#ifndef _ASN1_UTILS_H_ +#define _ASN1_UTILS_H_ + +int decode_t_reordering(int v); +int decode_t_status_prohibit(int v); +int decode_t_poll_retransmit(int v); +int decode_poll_pdu(int v); +int decode_poll_byte(int v); +int decode_max_retx_threshold(int v); +int decode_sn_field_length(int v); + +#endif /* _ASN1_UTILS_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_entity.c b/openair2/LAYER2/rlc_v2/rlc_entity.c new file mode 100644 index 0000000000..d774e2b7e1 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity.c @@ -0,0 +1,144 @@ +/* + * 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 "rlc_entity.h" + +#include + +#include "rlc_entity_am.h" +#include "rlc_entity_um.h" + +#include "LOG/log.h" + +rlc_entity_t *new_rlc_entity_am( + int rx_maxsize, + int tx_maxsize, + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*sdu_successful_delivery)(void *sdu_successful_delivery_data, + struct rlc_entity_t *entity, + int sdu_id), + void *sdu_successful_delivery_data, + void (*max_retx_reached)(void *max_retx_reached_data, + struct rlc_entity_t *entity), + void *max_retx_reached_data, + int t_reordering, + int t_status_prohibit, + int t_poll_retransmit, + int poll_pdu, + int poll_byte, + int max_retx_threshold) +{ + rlc_entity_am_t *ret; + + ret = calloc(1, sizeof(rlc_entity_am_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ret->common.recv_pdu = rlc_entity_am_recv_pdu; + ret->common.buffer_status = rlc_entity_am_buffer_status; + ret->common.generate_pdu = rlc_entity_am_generate_pdu; + + ret->common.recv_sdu = rlc_entity_am_recv_sdu; + + ret->common.set_time = rlc_entity_am_set_time; + + ret->common.discard_sdu = rlc_entity_am_discard_sdu; + + ret->common.reestablishment = rlc_entity_am_reestablishment; + + ret->common.delete = rlc_entity_am_delete; + + ret->common.deliver_sdu = deliver_sdu; + ret->common.deliver_sdu_data = deliver_sdu_data; + + ret->common.sdu_successful_delivery = sdu_successful_delivery; + ret->common.sdu_successful_delivery_data = sdu_successful_delivery_data; + + ret->common.max_retx_reached = max_retx_reached; + ret->common.max_retx_reached_data = max_retx_reached_data; + + ret->rx_maxsize = rx_maxsize; + ret->tx_maxsize = tx_maxsize; + ret->t_reordering = t_reordering; + ret->t_status_prohibit = t_status_prohibit; + ret->t_poll_retransmit = t_poll_retransmit; + ret->poll_pdu = poll_pdu; + ret->poll_byte = poll_byte; + ret->max_retx_threshold = max_retx_threshold; + + return (rlc_entity_t *)ret; +} + +rlc_entity_t *new_rlc_entity_um( + int rx_maxsize, + int tx_maxsize, + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + int t_reordering, + int sn_field_length) +{ + rlc_entity_um_t *ret; + + ret = calloc(1, sizeof(rlc_entity_um_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ret->common.recv_pdu = rlc_entity_um_recv_pdu; + ret->common.buffer_status = rlc_entity_um_buffer_status; + ret->common.generate_pdu = rlc_entity_um_generate_pdu; + + ret->common.recv_sdu = rlc_entity_um_recv_sdu; + + ret->common.set_time = rlc_entity_um_set_time; + + ret->common.discard_sdu = rlc_entity_um_discard_sdu; + + ret->common.reestablishment = rlc_entity_um_reestablishment; + + ret->common.delete = rlc_entity_um_delete; + + ret->common.deliver_sdu = deliver_sdu; + ret->common.deliver_sdu_data = deliver_sdu_data; + + ret->sn_field_length = sn_field_length; + ret->rx_maxsize = rx_maxsize; + ret->tx_maxsize = tx_maxsize; + ret->t_reordering = t_reordering; + + if (sn_field_length == 5) + ret->sn_modulus = 32; + else if (sn_field_length == 10) + ret->sn_modulus = 1024; + else { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + ret->window_size = ret->sn_modulus / 2; + + return (rlc_entity_t *)ret; +} diff --git a/openair2/LAYER2/rlc_v2/rlc_entity.h b/openair2/LAYER2/rlc_v2/rlc_entity.h new file mode 100644 index 0000000000..c9b35204f0 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity.h @@ -0,0 +1,97 @@ +/* + * 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 _RLC_ENTITY_H_ +#define _RLC_ENTITY_H_ + +#include + +#define SDU_MAX 16000 /* maximum PDCP SDU size is 8188, let's take more */ + +typedef struct { + int status_size; + int tx_size; + int retx_size; +} rlc_entity_buffer_status_t; + +typedef struct rlc_entity_t { + /* functions provided by the RLC module */ + void (*recv_pdu)(struct rlc_entity_t *entity, char *buffer, int size); + rlc_entity_buffer_status_t (*buffer_status)( + struct rlc_entity_t *entity, int maxsize); + int (*generate_pdu)(struct rlc_entity_t *entity, char *buffer, int size); + + void (*recv_sdu)(struct rlc_entity_t *entity, char *buffer, int size, + int sdu_id); + + void (*set_time)(struct rlc_entity_t *entity, uint64_t now); + + void (*discard_sdu)(struct rlc_entity_t *entity, int sdu_id); + + void (*reestablishment)(struct rlc_entity_t *entity); + + void (*delete)(struct rlc_entity_t *entity); + + /* callbacks provided to the RLC module */ + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size); + void *deliver_sdu_data; + + void (*sdu_successful_delivery)(void *sdu_successful_delivery_data, + struct rlc_entity_t *entity, + int sdu_id); + void *sdu_successful_delivery_data; + + void (*max_retx_reached)(void *max_retx_reached_data, + struct rlc_entity_t *entity); + void *max_retx_reached_data; +} rlc_entity_t; + +rlc_entity_t *new_rlc_entity_am( + int rx_maxsize, + int tx_maxsize, + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*sdu_successful_delivery)(void *sdu_successful_delivery_data, + struct rlc_entity_t *entity, + int sdu_id), + void *sdu_successful_delivery_data, + void (*max_retx_reached)(void *max_retx_reached_data, + struct rlc_entity_t *entity), + void *max_retx_reached_data, + int t_reordering, + int t_status_prohibit, + int t_poll_retransmit, + int poll_pdu, + int poll_byte, + int max_retx_threshold); + +rlc_entity_t *new_rlc_entity_um( + int rx_maxsize, + int tx_maxsize, + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + int t_reordering, + int sn_field_length); + +#endif /* _RLC_ENTITY_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_entity_am.c b/openair2/LAYER2/rlc_v2/rlc_entity_am.c new file mode 100644 index 0000000000..b4f3d2f47c --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity_am.c @@ -0,0 +1,1700 @@ +/* + * 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 "rlc_entity_am.h" +#include "rlc_pdu.h" + +#include +#include + +#include "LOG/log.h" + +/*************************************************************************/ +/* PDU RX functions */ +/*************************************************************************/ + +static int modulus_rx(rlc_entity_am_t *entity, int a) +{ + /* as per 36.322 7.1, modulus base is vr(r) and modulus is 1024 for rx */ + int r = a - entity->vr_r; + if (r < 0) r += 1024; + return r; +} + +/* used in both RX and TX processing */ +static int modulus_tx(rlc_entity_am_t *entity, int a) +{ + /* as per 36.322 7.1, modulus base is vt(a) and modulus is 1024 for tx */ + int r = a - entity->vt_a; + if (r < 0) r += 1024; + return r; +} + +static int sn_in_recv_window(void *_entity, int sn) +{ + rlc_entity_am_t *entity = _entity; + int mod_sn = modulus_rx(entity, sn); + /* we simplify vr(r)<=snrx_list; + + while (l != NULL) { + if (l->sn == sn && l->so <= so && + l->so + l->size - l->data_offset >= so + data_size) + return 1; + l = l->next; + } + + return 0; +} + +static int rlc_am_segment_full(rlc_entity_am_t *entity, int sn) +{ + rlc_rx_pdu_segment_t *l = entity->rx_list; + int last_byte; + int new_last_byte; + + last_byte = -1; + while (l != NULL) { + if (l->sn == sn) + break; + l = l->next; + } + while (l != NULL && l->sn == sn) { + if (l->so > last_byte + 1) + return 0; + if (l->is_last) + return 1; + new_last_byte = l->so + l->size - l->data_offset - 1; + if (new_last_byte > last_byte) + last_byte = new_last_byte; + l = l->next; + } + return 0; +} + +/* return 1 if the new segment has some data to consume, 0 if not */ +static int rlc_am_reassemble_next_segment(rlc_am_reassemble_t *r) +{ + int rf; + int sn; + + r->sdu_offset = r->start->data_offset; + + rlc_pdu_decoder_init(&r->dec, r->start->data, r->start->size); + + rlc_pdu_decoder_get_bits(&r->dec, 1); /* dc */ + rf = rlc_pdu_decoder_get_bits(&r->dec, 1); + rlc_pdu_decoder_get_bits(&r->dec, 1); /* p */ + r->fi = rlc_pdu_decoder_get_bits(&r->dec, 2); + r->e = rlc_pdu_decoder_get_bits(&r->dec, 1); + sn = rlc_pdu_decoder_get_bits(&r->dec, 10); + if (rf) { + rlc_pdu_decoder_get_bits(&r->dec, 1); /* lsf */ + r->so = rlc_pdu_decoder_get_bits(&r->dec, 15); + } else { + r->so = 0; + } + + if (r->e) { + r->e = rlc_pdu_decoder_get_bits(&r->dec, 1); + r->sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else + r->sdu_len = r->start->size - r->sdu_offset; + + /* new sn: read starts from PDU byte 0 */ + if (sn != r->sn) { + r->pdu_byte = 0; + r->sn = sn; + } + + r->data_pos = r->start->data_offset + r->pdu_byte - r->so; + + /* TODO: remove this check, it is useless, data has been validated before */ + if (r->pdu_byte < r->so) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + /* if pdu_byte is not in [so .. so+len-1] then all bytes from this segment + * have already been consumed + */ + if (r->pdu_byte >= r->so + r->start->size - r->start->data_offset) + return 0; + + /* go to correct SDU */ + while (r->pdu_byte >= r->so + (r->sdu_offset - r->start->data_offset) + r->sdu_len) { + r->sdu_offset += r->sdu_len; + if (r->e) { + r->e = rlc_pdu_decoder_get_bits(&r->dec, 1); + r->sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else { + r->sdu_len = r->start->size - r->sdu_offset; + } + } + + return 1; +} + +static void rlc_am_reassemble(rlc_entity_am_t *entity) +{ + rlc_am_reassemble_t *r = &entity->reassemble; + + while (r->start != NULL) { + if (r->sdu_pos >= SDU_MAX) { + /* TODO: proper error handling (discard PDUs with current sn from + * reassembly queue? something else?) + */ + LOG_E(RLC, "%s:%d:%s: bad RLC PDU\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + r->sdu[r->sdu_pos] = r->start->data[r->data_pos]; + r->sdu_pos++; + r->data_pos++; + r->pdu_byte++; + if (r->data_pos == r->sdu_offset + r->sdu_len) { + /* all bytes of SDU are consumed, check if SDU is fully there. + * It is if the data pointer is not at the end of the PDU segment + * or if 'fi' & 1 == 0 + */ + if (r->data_pos != r->start->size || + (r->fi & 1) == 0) { + /* SDU is full - deliver to higher layer */ + entity->common.deliver_sdu(entity->common.deliver_sdu_data, + (rlc_entity_t *)entity, + r->sdu, r->sdu_pos); + r->sdu_pos = 0; + } + if (r->data_pos != r->start->size) { + /* not at the end, process next SDU */ + r->sdu_offset += r->sdu_len; + if (r->e) { + r->e = rlc_pdu_decoder_get_bits(&r->dec, 1); + r->sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else + r->sdu_len = r->start->size - r->sdu_offset; + } else { + /* all bytes are consumend, go to next segment not already fully + * processed, if any + */ + do { + rlc_rx_pdu_segment_t *e = r->start; + entity->rx_size -= e->size; + r->start = r->start->next; + rlc_rx_free_pdu_segment(e); + } while (r->start != NULL && !rlc_am_reassemble_next_segment(r)); + } + } + } +} + +static void rlc_am_reception_actions(rlc_entity_am_t *entity, + rlc_rx_pdu_segment_t *pdu_segment) +{ + int x = pdu_segment->sn; + int vr_ms; + int vr_r; + + if (modulus_rx(entity, x) >= modulus_rx(entity, entity->vr_h)) + entity->vr_h = (x + 1) % 1024; + + vr_ms = entity->vr_ms; + while (rlc_am_segment_full(entity, vr_ms)) + vr_ms = (vr_ms + 1) % 1024; + entity->vr_ms = vr_ms; + + if (x == entity->vr_r) { + vr_r = entity->vr_r; + while (rlc_am_segment_full(entity, vr_r)) { + /* move segments with sn=vr(r) from rx list to end of reassembly list */ + while (entity->rx_list != NULL && entity->rx_list->sn == vr_r) { + rlc_rx_pdu_segment_t *e = entity->rx_list; + entity->rx_list = e->next; + e->next = NULL; + if (entity->reassemble.start == NULL) { + entity->reassemble.start = e; + /* the list was empty, we need to init decoder */ + entity->reassemble.sn = -1; + if (!rlc_am_reassemble_next_segment(&entity->reassemble)) { + /* TODO: proper error recovery (or remove the test, it should not happen) */ + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + } else { + entity->reassemble.end->next = e; + } + entity->reassemble.end = e; + } + + /* update vr_r */ + vr_r = (vr_r + 1) % 1024; + } + entity->vr_r = vr_r; + } + + rlc_am_reassemble(entity); + + if (entity->t_reordering_start) { + int vr_x = entity->vr_x; + if (vr_x < entity->vr_r) vr_x += 1024; + if (vr_x == entity->vr_r || vr_x > entity->vr_r + 512) + entity->t_reordering_start = 0; + } + + if (entity->t_reordering_start == 0) { + if (sn_compare_rx(entity, entity->vr_h, entity->vr_r) > 0) { + entity->t_reordering_start = entity->t_current; + entity->vr_x = entity->vr_h; + } + } +} + +static void process_received_ack(rlc_entity_am_t *entity, int sn) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + + /* put all PDUs from wait and retransmit lists with SN < 'sn' to ack_list */ + + /* process wait list */ + head.next = entity->wait_list; + prev = &head; + cur = entity->wait_list; + while (cur != NULL) { + if (sn_compare_tx(entity, cur->sn, sn) < 0) { + /* remove from wait list */ + prev->next = cur->next; + /* put the PDU in the ack list */ + entity->ack_list = rlc_tx_pdu_list_add(sn_compare_tx, entity, + entity->ack_list, cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + entity->wait_list = head.next; + + /* process retransmit list */ + head.next = entity->retransmit_list; + prev = &head; + cur = entity->retransmit_list; + while (cur != NULL) { + if (sn_compare_tx(entity, cur->sn, sn) < 0) { + /* dec. retx_count in case we put this segment back in retransmit list + * in 'process_received_nack' + */ + cur->retx_count--; + /* remove from retransmit list */ + prev->next = cur->next; + /* put the PDU in the ack list */ + entity->ack_list = rlc_tx_pdu_list_add(sn_compare_tx, entity, + entity->ack_list, cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + entity->retransmit_list = head.next; + +} + +static void consider_retransmission(rlc_entity_am_t *entity, + rlc_tx_pdu_segment_t *cur) +{ + cur->retx_count++; + + /* let's report max RETX reached for all retx_count >= max_retx_threshold + * (specs say to report if retx_count == max_retx_threshold). + * Upper layers should react (radio link failure), so no big deal actually. + */ + if (cur->retx_count >= entity->max_retx_threshold) { + entity->common.max_retx_reached(entity->common.max_retx_reached_data, + (rlc_entity_t *)entity); + } + + /* let's put in retransmit list even if we are over max_retx_threshold. + * upper layers should deal with this condition, internally it's better + * for the RLC code to keep going with this segment (we only remove + * a segment that was ACKed) + */ + entity->retransmit_list = rlc_tx_pdu_list_add(sn_compare_tx, entity, + entity->retransmit_list, cur); +} + +static int so_overlap(int s1, int e1, int s2, int e2) +{ + if (s1 < s2) { + if (e1 == -1 || e1 >= s2) + return 1; + return 0; + } + if (e2 == -1 || s1 <= e2) + return 1; + return 0; +} + +static void process_received_nack(rlc_entity_am_t *entity, int sn, + int so_start, int so_end) +{ + /* put all PDU segments with SN == 'sn' and with an overlapping so start/end + * to the retransmit list + * source lists are ack list and wait list. + * Not sure if we should consider wait list, isn't the other end supposed + * to only NACK SNs lower than the ACK SN sent in the status PDU, in which + * case all potential PDU segments should all be in ack list when calling + * the current function? in doubt let's accept anything and thus process + * also wait list. + */ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + + /* check that VT(A) <= sn < VT(S) */ + if (!(sn_compare_tx(entity, entity->vt_a, sn) <= 0 && + sn_compare_tx(entity, sn, entity->vt_s) < 0)) + return; + + /* process wait list */ + head.next = entity->wait_list; + prev = &head; + cur = entity->wait_list; + while (cur != NULL) { + if (cur->sn == sn && + so_overlap(so_start, so_end, cur->so, cur->so + cur->data_size - 1)) { + /* remove from wait list */ + prev->next = cur->next; + /* consider the PDU segment for retransmission */ + consider_retransmission(entity, cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + entity->wait_list = head.next; + + /* process ack list */ + head.next = entity->ack_list; + prev = &head; + cur = entity->ack_list; + while (cur != NULL) { + if (cur->sn == sn && + so_overlap(so_start, so_end, cur->so, cur->so + cur->data_size - 1)) { + /* remove from ack list */ + prev->next = cur->next; + /* consider the PDU segment for retransmission */ + consider_retransmission(entity, cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + entity->ack_list = head.next; +} + +int tx_pdu_in_ack_list_full(rlc_tx_pdu_segment_t *pdu) +{ + int sn = pdu->sn; + int last_byte = -1; + int new_last_byte; + int is_last_seen = 0; + + while (pdu != NULL && pdu->sn == sn) { + if (pdu->so > last_byte + 1) return 0; + if (pdu->is_last) + is_last_seen = 1; + new_last_byte = pdu->so + pdu->data_size - 1; + if (new_last_byte > last_byte) + last_byte = new_last_byte; + pdu = pdu->next; + } + + return is_last_seen == 1; +} + +int tx_pdu_in_ack_list_size(rlc_tx_pdu_segment_t *pdu) +{ + int sn = pdu->sn; + int ret = 0; + + while (pdu != NULL && pdu->sn == sn) { + ret += pdu->data_size; + pdu = pdu->next; + } + + return ret; +} + +void ack_sdu_bytes(rlc_sdu_t *start, int start_byte, int sdu_size) +{ + rlc_sdu_t *cur = start; + int remaining_size = sdu_size; + + while (remaining_size) { + int cursize = cur->size - start_byte; + if (cursize > remaining_size) + cursize = remaining_size; + cur->acked_bytes += cursize; + remaining_size -= cursize; + /* start_byte is only meaningful for the 1st SDU, then it is 0 */ + start_byte = 0; + cur = cur->next; + } +} + +rlc_tx_pdu_segment_t *tx_list_remove_sn(rlc_tx_pdu_segment_t *list, int sn) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + + head.next = list; + cur = list; + prev = &head; + + while (cur != NULL) { + if (cur->sn == sn) { + prev->next = cur->next; + rlc_tx_free_pdu(cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + + return head.next; +} + +void cleanup_sdu_list(rlc_entity_am_t *entity) +{ + rlc_sdu_t head; + rlc_sdu_t *cur; + rlc_sdu_t *prev; + + /* remove fully acked SDUs, indicate successful delivery to upper layer */ + head.next = entity->tx_list; + cur = entity->tx_list; + prev = &head; + + while (cur != NULL) { + if (cur->acked_bytes == cur->size) { + prev->next = cur->next; + entity->tx_size -= cur->size; + entity->common.sdu_successful_delivery( + entity->common.sdu_successful_delivery_data, + (rlc_entity_t *)entity, cur->upper_layer_id); + rlc_free_sdu(cur); + entity->tx_end = prev; + cur = prev->next; + } else { + entity->tx_end = cur; + prev = cur; + cur = cur->next; + } + } + + entity->tx_list = head.next; + + /* if tx_end == head then it means that the list is now empty */ + if (entity->tx_end == &head) + entity->tx_end = NULL; +} + +static void finalize_ack_nack_processing(rlc_entity_am_t *entity) +{ + int sn; + rlc_tx_pdu_segment_t *cur = entity->ack_list; + int pdu_size; + + if (cur == NULL) + return; + + /* Remove full PDUs and ack the SDU bytes they cover. Start from SN == VT(A) + * and process increasing SNs until end of list or missing ACK or PDU not + * fully ACKed. + */ + while (cur != NULL && cur->sn == entity->vt_a && + tx_pdu_in_ack_list_full(cur)) { + sn = cur->sn; + entity->vt_a = (entity->vt_a + 1) % 1024; + pdu_size = tx_pdu_in_ack_list_size(cur); + ack_sdu_bytes(cur->start_sdu, cur->sdu_start_byte, pdu_size); + while (cur != NULL && cur->sn == sn) + cur = cur->next; + entity->ack_list = tx_list_remove_sn(entity->ack_list, sn); + } + + cleanup_sdu_list(entity); +} + +void rlc_entity_am_recv_pdu(rlc_entity_t *_entity, char *buffer, int size) +{ +#define R(d) do { if (rlc_pdu_decoder_in_error(&d)) goto err; } while (0) + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + rlc_pdu_decoder_t decoder; + rlc_pdu_decoder_t data_decoder; + rlc_pdu_decoder_t control_decoder; + + int dc; + int rf; + int p = 0; + int fi; + int e; + int sn; + int lsf; + int so; + + int cpt; + int e1; + int e2; + int ack_sn; + int nack_sn; + int so_start; + int so_end; + int control_e1; + int control_e2; + + int data_e; + int data_li; + + int packet_count; + int data_size; + int data_start; + int indicated_data_size; + + rlc_rx_pdu_segment_t *pdu_segment; + + rlc_pdu_decoder_init(&decoder, buffer, size); + dc = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + if (dc == 0) goto control; + + /* data PDU */ + rf = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + p = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + fi = rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder); + e = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + sn = rlc_pdu_decoder_get_bits(&decoder, 10); R(decoder); + + /* dicard PDU if rx buffer is full */ + if (entity->rx_size + size > entity->rx_maxsize) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, RX buffer full\n", + __FILE__, __LINE__, __FUNCTION__); + goto discard; + } + + if (!sn_in_recv_window(entity, sn)) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, sn out of window (sn %d vr_r %d)\n", + __FILE__, __LINE__, __FUNCTION__, + sn, entity->vr_r); + goto discard; + } + + if (rf) { + lsf = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + so = rlc_pdu_decoder_get_bits(&decoder, 15); R(decoder); + } else { + lsf = 1; + so = 0; + } + + packet_count = 1; + + /* go to start of data */ + indicated_data_size = 0; + data_decoder = decoder; + data_e = e; + while (data_e) { + data_e = rlc_pdu_decoder_get_bits(&data_decoder, 1); R(data_decoder); + data_li = rlc_pdu_decoder_get_bits(&data_decoder, 11); R(data_decoder); + if (data_li == 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, li == 0\n", + __FILE__, __LINE__, __FUNCTION__); + goto discard; + } + indicated_data_size += data_li; + packet_count++; + } + rlc_pdu_decoder_align(&data_decoder); + + data_start = data_decoder.byte; + data_size = size - data_start; + + if (data_size <= 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, wrong data size (sum of LI %d data size %d)\n", + __FILE__, __LINE__, __FUNCTION__, + indicated_data_size, data_size); + goto discard; + } + if (indicated_data_size >= data_size) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, bad LIs (sum of LI %d data size %d)\n", + __FILE__, __LINE__, __FUNCTION__, + indicated_data_size, data_size); + goto discard; + } + + /* discard segment if all the bytes of the segment are already there */ + if (segment_already_received(entity, sn, so, data_size)) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, already received\n", + __FILE__, __LINE__, __FUNCTION__); + goto discard; + } + + char *fi_str[] = { + "first byte: YES last byte: YES", + "first byte: YES last byte: NO", + "first byte: NO last byte: YES", + "first byte: NO last byte: NO", + }; + + LOG_D(RLC, "found %d packets, data size %d data start %d [fi %d %s] (sn %d) (p %d)\n", + packet_count, data_size, data_decoder.byte, fi, fi_str[fi], sn, p); + + /* put in pdu reception list */ + entity->rx_size += size; + pdu_segment = rlc_rx_new_pdu_segment(sn, so, size, lsf, buffer, data_start); + entity->rx_list = rlc_rx_pdu_segment_list_add(sn_compare_rx, entity, + entity->rx_list, pdu_segment); + + /* do reception actions (36.322 5.1.3.2.3) */ + rlc_am_reception_actions(entity, pdu_segment); + + if (p) { + /* 36.322 5.2.3 says status triggering should be delayed + * until x < VR(MS) or x >= VR(MR). This is not clear (what + * is x then? we keep the same?). So let's trigger no matter what. + */ + int vr_mr = (entity->vr_r + 512) % 1024; + entity->status_triggered = 1; + if (!(sn_compare_rx(entity, sn, entity->vr_ms) < 0 || + sn_compare_rx(entity, sn, vr_mr) >= 0)) { + LOG_D(RLC, "%s:%d:%s: warning: STATUS trigger should be delayed, according to specs\n", + __FILE__, __LINE__, __FUNCTION__); + } + } + + return; + +control: + cpt = rlc_pdu_decoder_get_bits(&decoder, 3); R(decoder); + if (cpt != 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, CPT not 0 (%d)\n", + __FILE__, __LINE__, __FUNCTION__, cpt); + goto discard; + } + ack_sn = rlc_pdu_decoder_get_bits(&decoder, 10); R(decoder); + e1 = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + + /* let's try to parse the control PDU once to check consistency */ + control_decoder = decoder; + control_e1 = e1; + while (control_e1) { + rlc_pdu_decoder_get_bits(&control_decoder, 10); R(control_decoder); /* NACK_SN */ + control_e1 = rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); + control_e2 = rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); + if (control_e2) { + rlc_pdu_decoder_get_bits(&control_decoder, 15); R(control_decoder); /* SOstart */ + rlc_pdu_decoder_get_bits(&control_decoder, 15); R(control_decoder); /* SOend */ + } + } + + /* 36.322 5.2.2.2 says to stop t_poll_retransmit if a ACK or NACK is + * received for the SN 'poll_sn' + */ + if (sn_compare_tx(entity, entity->poll_sn, ack_sn) < 0) + entity->t_poll_retransmit_start = 0; + + /* at this point, accept the PDU even if the actual values + * may be incorrect (eg. if so_start > so_end) + */ + process_received_ack(entity, ack_sn); + + while (e1) { + nack_sn = rlc_pdu_decoder_get_bits(&decoder, 10); R(decoder); + e1 = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + e2 = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + if (e2) { + so_start = rlc_pdu_decoder_get_bits(&decoder, 15); R(decoder); + so_end = rlc_pdu_decoder_get_bits(&decoder, 15); R(decoder); + if (so_end < so_start) { + LOG_W(RLC, "%s:%d:%s: warning, bad so start/end, NACK the whole PDU (sn %d)\n", + __FILE__, __LINE__, __FUNCTION__, nack_sn); + so_start = 0; + so_end = -1; + } + /* special value 0x7fff indicates 'all bytes to the end' */ + if (so_end == 0x7fff) + so_end = -1; + } else { + so_start = 0; + so_end = -1; + } + process_received_nack(entity, nack_sn, so_start, so_end); + + /* 36.322 5.2.2.2 says to stop t_poll_retransmit if a ACK or NACK is + * received for the SN 'poll_sn' + */ + if (entity->poll_sn == nack_sn) + entity->t_poll_retransmit_start = 0; + } + + finalize_ack_nack_processing(entity); + + return; + +err: + LOG_W(RLC, "%s:%d:%s: error decoding PDU, discarding\n", __FILE__, __LINE__, __FUNCTION__); + goto discard; + +discard: + if (p) + entity->status_triggered = 1; + +#undef R +} + +/*************************************************************************/ +/* TX functions */ +/*************************************************************************/ + +static int pdu_size(rlc_entity_am_t *entity, rlc_tx_pdu_segment_t *pdu) +{ + int header_size; + int sdu_count; + int data_size; + int li_bits; + rlc_sdu_t *sdu; + + header_size = 2; + if (pdu->is_segment) + header_size += 2; + + data_size = pdu->data_size; + + sdu = pdu->start_sdu; + + sdu_count = 1; + data_size -= sdu->size - pdu->sdu_start_byte; + sdu = sdu->next; + + while (data_size > 0) { + sdu_count++; + data_size -= sdu->size; + sdu = sdu->next; + } + + li_bits = 12 * (sdu_count - 1); + header_size += (li_bits + 7) / 8; + + return header_size + pdu->data_size; +} + +static int header_size(int sdu_count) +{ + int bits = 16 + 12 * (sdu_count - 1); + /* padding if we have to */ + return (bits + 7) / 8; +} + +typedef struct { + int sdu_count; + int data_size; + int header_size; +} tx_pdu_size_t; + +static tx_pdu_size_t compute_new_pdu_size(rlc_entity_am_t *entity, int maxsize) +{ + tx_pdu_size_t ret; + int sdu_count; + int sdu_size; + int pdu_data_size; + rlc_sdu_t *sdu; + + int vt_ms = (entity->vt_a + 512) % 1024; + + ret.sdu_count = 0; + ret.data_size = 0; + ret.header_size = 0; + + /* sn out of window? nothing to do */ + if (!(sn_compare_tx(entity, entity->vt_s, entity->vt_a) >= 0 && + sn_compare_tx(entity, entity->vt_s, vt_ms) < 0)) + return ret; + + /* TX PDU - let's make the biggest PDU we can with the SDUs we have */ + sdu_count = 0; + pdu_data_size = 0; + sdu = entity->tx_list; + while (sdu != NULL) { + /* include SDU only if it has not been fully included in PDUs already */ + if (sdu->next_byte != sdu->size) { + int new_header_size = header_size(sdu_count + 1); + /* if we cannot put new header + at least 1 byte of data then over */ + if (new_header_size + pdu_data_size + 1 > maxsize) + break; + sdu_count++; + /* only include the bytes of this SDU not included in PDUs already */ + sdu_size = sdu->size - sdu->next_byte; + /* don't feed more than 'maxsize' bytes */ + if (new_header_size + pdu_data_size + sdu_size > maxsize) + sdu_size = maxsize - new_header_size - pdu_data_size; + pdu_data_size += sdu_size; + /* if we put more than 2^11-1 bytes then the LI field cannot be used, + * so this is the last SDU we can put + */ + if (sdu_size > 2047) + break; + } + sdu = sdu->next; + } + + if (sdu_count) { + ret.sdu_count = sdu_count; + ret.data_size = pdu_data_size; + ret.header_size = header_size(sdu_count); + } + + return ret; +} + +static int status_size(rlc_entity_am_t *entity, int maxsize) +{ + /* let's count bits */ + int bits = 15; /* minimum size is 15 (header+ack_sn+e1) */ + int sn; + + maxsize *= 8; + + if (bits > maxsize) { + LOG_W(RLC, "%s:%d:%s: warning: cannot generate status PDU, not enough room\n", + __FILE__, __LINE__, __FUNCTION__); + return 0; + } + + /* each NACK adds 12 bits */ + sn = entity->vr_r; + while (bits + 12 <= maxsize && sn_compare_rx(entity, sn, entity->vr_ms) < 0) { + if (!(rlc_am_segment_full(entity, sn))) + bits += 12; + sn = (sn + 1) % 1024; + } + + return (bits + 7) / 8; +} + +static int generate_status(rlc_entity_am_t *entity, char *buffer, int size) +{ + /* let's count bits */ + int bits = 15; /* minimum size is 15 (header+ack_sn+e1) */ + int sn; + rlc_pdu_encoder_t encoder; + int has_nack = 0; + int ack; + + rlc_pdu_encoder_init(&encoder, buffer, size); + + size *= 8; + + if (bits > size) { + LOG_W(RLC, "%s:%d:%s: warning: cannot generate status PDU, not enough room\n", + __FILE__, __LINE__, __FUNCTION__); + return 0; + } + + /* header */ + rlc_pdu_encoder_put_bits(&encoder, 0, 1); /* D/C */ + rlc_pdu_encoder_put_bits(&encoder, 0, 3); /* CPT */ + + /* reserve room for ACK (it will be set after putting the NACKs) */ + rlc_pdu_encoder_put_bits(&encoder, 0, 10); + + /* at this point, ACK is VR(R) */ + ack = entity->vr_r; + + /* each NACK adds 12 bits */ + sn = entity->vr_r; + while (bits + 12 <= size && sn_compare_rx(entity, sn, entity->vr_ms) < 0) { + if (!(rlc_am_segment_full(entity, sn))) { + /* put previous e1 (is 1) */ + rlc_pdu_encoder_put_bits(&encoder, 1, 1); + /* if previous was NACK, put previous e2 (0, we don't do 'so' thing) */ + if (has_nack) + rlc_pdu_encoder_put_bits(&encoder, 0, 1); + /* put NACKed sn */ + rlc_pdu_encoder_put_bits(&encoder, sn, 10); + has_nack = 1; + bits += 12; + } else { + /* this sn is full and we put all NACKs before it, use it for ACK */ + ack = (sn + 1) % 1024; + } + sn = (sn + 1) % 1024; + } + + /* go to highest full sn+1 for ACK, VR(MS) is the limit */ + while (sn_compare_rx(entity, sn, entity->vr_ms) < 0 && + rlc_am_segment_full(entity, sn)) { + ack = (sn + 1) % 1024; + sn = (sn + 1) % 1024; + } + + /* at this point, if last put was NACK then put 2 bits else put 1 bit */ + if (has_nack) + rlc_pdu_encoder_put_bits(&encoder, 0, 2); + else + rlc_pdu_encoder_put_bits(&encoder, 0, 1); + + rlc_pdu_encoder_align(&encoder); + + /* let's put the ACK */ + buffer[0] |= ack >> 6; + buffer[1] |= (ack & 0x3f) << 2; + + /* reset the trigger */ + entity->status_triggered = 0; + + /* start t_status_prohibit */ + entity->t_status_prohibit_start = entity->t_current; + + return encoder.byte; +} + +int transmission_buffer_empty(rlc_entity_am_t *entity) +{ + rlc_sdu_t *sdu; + + /* is transmission buffer empty? */ + sdu = entity->tx_list; + while (sdu != NULL) { + if (sdu->next_byte != sdu->size) + return 0; + sdu = sdu->next; + } + return 1; +} + +int check_poll_after_pdu_assembly(rlc_entity_am_t *entity) +{ + int retransmission_buffer_empty; + int window_stalling; + int vt_ms; + + /* is retransmission buffer empty? */ + if (entity->retransmit_list == NULL) + retransmission_buffer_empty = 1; + else + retransmission_buffer_empty = 0; + + /* is window stalling? */ + vt_ms = (entity->vt_a + 512) % 1024; + if (!(sn_compare_tx(entity, entity->vt_s, entity->vt_a) >= 0 && + sn_compare_tx(entity, entity->vt_s, vt_ms) < 0)) + window_stalling = 1; + else + window_stalling = 0; + + return (transmission_buffer_empty(entity) && retransmission_buffer_empty) || + window_stalling; +} + +void include_poll(rlc_entity_am_t *entity, char *buffer) +{ + /* set the P bit to 1 */ + buffer[0] |= 0x20; + + entity->pdu_without_poll = 0; + entity->byte_without_poll = 0; + + /* set POLL_SN to VT(S) - 1 */ + entity->poll_sn = (entity->vt_s + 1023) % 1024; + + /* start t_poll_retransmit */ + entity->t_poll_retransmit_start = entity->t_current; +} + +static int serialize_pdu(rlc_entity_am_t *entity, char *buffer, int bufsize, + rlc_tx_pdu_segment_t *pdu, int p) +{ + int first_sdu_full; + int last_sdu_full; + int sdu_next_byte; + rlc_sdu_t *sdu; + int i; + int cursize; + rlc_pdu_encoder_t encoder; + int fi; + int e; + int li; + char *out; + int outpos; + int sdu_count; + int header_size; + int sdu_start_byte; + + first_sdu_full = pdu->sdu_start_byte == 0; + + /* is last SDU full? (and also compute sdu_count) */ + last_sdu_full = 1; + sdu = pdu->start_sdu; + sdu_next_byte = pdu->sdu_start_byte; + cursize = 0; + sdu_count = 0; + while (cursize != pdu->data_size) { + int sdu_size = sdu->size - sdu_next_byte; + sdu_count++; + if (cursize + sdu_size > pdu->data_size) { + last_sdu_full = 0; + break; + } + cursize += sdu_size; + sdu = sdu->next; + sdu_next_byte = 0; + } + + /* generate header */ + rlc_pdu_encoder_init(&encoder, buffer, bufsize); + + rlc_pdu_encoder_put_bits(&encoder, 1, 1); /* D/C: 1 = data */ + rlc_pdu_encoder_put_bits(&encoder, pdu->is_segment, 1); /* RF */ + rlc_pdu_encoder_put_bits(&encoder, 0, 1); /* P: reserve, set later */ + + fi = 0; + if (!first_sdu_full) + fi |= 0x02; + if (!last_sdu_full) + fi |= 0x01; + rlc_pdu_encoder_put_bits(&encoder, fi, 2); /* FI */ + + /* to understand the logic for Es and LIs: + * If we have: + * 1 SDU: E=0 + * + * 2 SDUs: E=1 + * then: E=0 LI(sdu[0]) + * + * 3 SDUs: E=1 + * then: E=1 LI(sdu[0]) + * then: E=0 LI(sdu[1]) + * + * 4 SDUs: E=1 + * then: E=1 LI(sdu[0]) + * then: E=1 LI(sdu[1]) + * then: E=0 LI(sdu[2]) + */ + if (sdu_count >= 2) + e = 1; + else + e = 0; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + + rlc_pdu_encoder_put_bits(&encoder, pdu->sn, 10); /* SN */ + + if (pdu->is_segment) { + rlc_pdu_encoder_put_bits(&encoder, pdu->is_last, 1); /* LSF */ + rlc_pdu_encoder_put_bits(&encoder, pdu->so, 15); /* SO */ + } + + /* put LIs */ + sdu = pdu->start_sdu; + /* first SDU */ + li = sdu->size - pdu->sdu_start_byte; + /* put E+LI only if at least 2 SDUs */ + if (sdu_count >= 2) { + /* E is 1 if at least 3 SDUs */ + if (sdu_count >= 3) + e = 1; + else + e = 0; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */ + } + /* next SDUs, but not the last (no LI for the last) */ + sdu = sdu->next; + for (i = 2; i < sdu_count; i++, sdu = sdu->next) { + if (i != sdu_count - 1) + e = 1; + else + e = 0; + li = sdu->size; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */ + } + + rlc_pdu_encoder_align(&encoder); + + header_size = encoder.byte; + + /* generate data */ + out = buffer + header_size; + sdu = pdu->start_sdu; + sdu_start_byte = pdu->sdu_start_byte; + outpos = 0; + for (i = 0; i < sdu_count; i++, sdu = sdu->next) { + li = sdu->size - sdu_start_byte; + if (outpos + li >= pdu->data_size) + li = pdu->data_size - outpos; + memcpy(out+outpos, sdu->data + sdu_start_byte, li); + outpos += li; + sdu_start_byte = 0; + } + + if (p) + include_poll(entity, buffer); + + return header_size + pdu->data_size; +} + +static int generate_tx_pdu(rlc_entity_am_t *entity, char *buffer, int bufsize) +{ + int vt_ms; + tx_pdu_size_t pdu_size; + rlc_sdu_t *sdu; + int i; + int cursize; + int p; + rlc_tx_pdu_segment_t *pdu; + + /* sn out of window? do nothing */ + vt_ms = (entity->vt_a + 512) % 1024; + if (!(sn_compare_tx(entity, entity->vt_s, entity->vt_a) >= 0 && + sn_compare_tx(entity, entity->vt_s, vt_ms) < 0)) + return 0; + + pdu_size = compute_new_pdu_size(entity, bufsize); + if (pdu_size.sdu_count == 0) + return 0; + + pdu = rlc_tx_new_pdu(); + + pdu->sn = entity->vt_s; + entity->vt_s = (entity->vt_s + 1) % 1024; + + /* go to first SDU (skip those already fully processed) */ + sdu = entity->tx_list; + while (sdu->next_byte == sdu->size) + sdu = sdu->next; + + pdu->start_sdu = sdu; + + pdu->sdu_start_byte = sdu->next_byte; + + pdu->so = 0; + pdu->is_segment = 0; + pdu->is_last = 1; + /* to conform to specs' logic, put -1 (specs say "for 1st retransmission + * put 0 otherwise increase", let's put -1 and always increase when the + * segment goes to retransmit list) + */ + pdu->retx_count = -1; + + /* reserve SDU bytes */ + cursize = 0; + for (i = 0; i < pdu_size.sdu_count; i++, sdu = sdu->next) { + int sdu_size = sdu->size - sdu->next_byte; + if (cursize + sdu_size > pdu_size.data_size) + sdu_size = pdu_size.data_size - cursize; + sdu->next_byte += sdu_size; + cursize += sdu_size; + } + + pdu->data_size = cursize; + + /* put PDU at the end of the wait list */ + entity->wait_list = rlc_tx_pdu_list_append(entity->wait_list, pdu); + + /* polling actions for a new PDU */ + entity->pdu_without_poll++; + entity->byte_without_poll += pdu_size.data_size; + if ((entity->poll_pdu != -1 && + entity->pdu_without_poll >= entity->poll_pdu) || + (entity->poll_byte != -1 && + entity->byte_without_poll >= entity->poll_byte)) + p = 1; + else + p = check_poll_after_pdu_assembly(entity); + + if (entity->force_poll) { + p = 1; + entity->force_poll = 0; + } + + return serialize_pdu(entity, buffer, bufsize, pdu, p); +} + +static void resegment(rlc_tx_pdu_segment_t *pdu, int size) +{ + rlc_tx_pdu_segment_t *new_pdu; + rlc_sdu_t *sdu; + int sdu_count; + int pdu_header_size; + int pdu_data_size; + int sdu_pos; + int sdu_bytes_to_take; + + /* PDU segment too big, cut in two parts so that first part fits into + * size bytes (including header) + */ + sdu = pdu->start_sdu; + pdu_data_size = 0; + sdu_pos = pdu->sdu_start_byte; + sdu_count = 0; + while (1) { + /* can we put a new header and at least one byte of data? */ + /* header has 2 more bytes for SO */ + pdu_header_size = 2 + header_size(sdu_count + 1); + if (pdu_header_size + pdu_data_size + 1 > size) { + /* no we can't, stop here */ + break; + } + /* yes we can, go ahead */ + sdu_count++; + sdu_bytes_to_take = sdu->size - sdu_pos; + if (pdu_header_size + pdu_data_size + sdu_bytes_to_take > size) { + sdu_bytes_to_take = size - (pdu_header_size + pdu_data_size); + } + sdu_pos += sdu_bytes_to_take; + if (sdu_pos == sdu->size) { + sdu = sdu->next; + sdu_pos = 0; + } + pdu_data_size += sdu_bytes_to_take; + } + + new_pdu = rlc_tx_new_pdu(); + pdu->is_segment = 1; + *new_pdu = *pdu; + + new_pdu->so = pdu->so + pdu_data_size; + new_pdu->data_size = pdu->data_size - pdu_data_size; + new_pdu->start_sdu = sdu; + new_pdu->sdu_start_byte = sdu_pos; + + pdu->is_last = 0; + pdu->data_size = pdu_data_size; + pdu->next = new_pdu; +} + +static int generate_retx_pdu(rlc_entity_am_t *entity, char *buffer, int size) +{ + rlc_tx_pdu_segment_t *pdu; + int orig_size; + int p; + + pdu = entity->retransmit_list; + orig_size = pdu_size(entity, pdu); + + if (orig_size > size) { + /* we can't resegment if size is less than 5 + * (4 bytes for header, 1 byte for data) + */ + if (size < 5) + return 0; + resegment(pdu, size); + } + + /* remove from retransmit list and put in wait list */ + entity->retransmit_list = pdu->next; + entity->wait_list = rlc_tx_pdu_list_add(sn_compare_tx, entity, + entity->wait_list, pdu); + + p = check_poll_after_pdu_assembly(entity); + + if (entity->force_poll) { + p = 1; + entity->force_poll = 0; + } + + return serialize_pdu(entity, buffer, orig_size, pdu, p); +} + +static int status_to_report(rlc_entity_am_t *entity) +{ + return entity->status_triggered && + (entity->t_status_prohibit_start == 0 || + entity->t_current - entity->t_status_prohibit_start > + entity->t_status_prohibit); +} + +static int retx_pdu_size(rlc_entity_am_t *entity, int maxsize) +{ + int size; + + if (entity->retransmit_list == NULL) + return 0; + + size = pdu_size(entity, entity->retransmit_list); + if (size <= maxsize) + return size; + + /* we can segment head of retransmist list if maxsize is large enough + * to hold a PDU segment with at least 1 data byte (so 5 bytes: 4 bytes + * header + 1 byte data) + */ + if (maxsize < 5) + return 0; + + /* a later segmentation of the head of retransmit list will generate a pdu + * of maximum size 'maxsize' (can be less) + */ + return maxsize; +} + +rlc_entity_buffer_status_t rlc_entity_am_buffer_status( + rlc_entity_t *_entity, int maxsize) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + rlc_entity_buffer_status_t ret; + tx_pdu_size_t tx_size; + + /* status PDU, if we have to */ + if (status_to_report(entity)) + ret.status_size = status_size(entity, maxsize); + else + ret.status_size = 0; + + /* TX PDU */ + /* todo: if an SDU has size >2047 in the tx list then processing + * stops and computed size will not be accurate. Change the computation + * to be more accurate (if needed). + */ + tx_size = compute_new_pdu_size(entity, maxsize); + ret.tx_size = tx_size.data_size + tx_size.header_size; + + /* reTX PDU */ + /* todo: report size of all available data, not just first PDU */ + ret.retx_size = retx_pdu_size(entity, maxsize); + + return ret; +} + +int rlc_entity_am_generate_pdu(rlc_entity_t *_entity, char *buffer, int size) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + int ret; + + if (status_to_report(entity)) { + ret = generate_status(entity, buffer, size); + if (ret != 0) + return ret; + } + + if (entity->retransmit_list != NULL) { + ret = generate_retx_pdu(entity, buffer, size); + if (ret != 0) + return ret; + } + + return generate_tx_pdu(entity, buffer, size); +} + +/*************************************************************************/ +/* SDU RX functions */ +/*************************************************************************/ + +void rlc_entity_am_recv_sdu(rlc_entity_t *_entity, char *buffer, int size, + int sdu_id) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + rlc_sdu_t *sdu; + + if (size > SDU_MAX) { + LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n", + __FILE__, __LINE__, __FUNCTION__, size); + exit(1); + } + + if (entity->tx_size + size > entity->tx_maxsize) { + LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n", + __FILE__, __LINE__, __FUNCTION__); + return; + } + + entity->tx_size += size; + + sdu = rlc_new_sdu(buffer, size, sdu_id); + rlc_sdu_list_add(&entity->tx_list, &entity->tx_end, sdu); +} + +/*************************************************************************/ +/* time/timers */ +/*************************************************************************/ + +static void check_t_poll_retransmit(rlc_entity_am_t *entity) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + int sn; + + /* 36.322 5.2.2.3 */ + /* did t_poll_retransmit expire? */ + if (entity->t_poll_retransmit_start == 0 || + entity->t_current <= entity->t_poll_retransmit_start + + entity->t_poll_retransmit) + return; + + /* stop timer */ + entity->t_poll_retransmit_start = 0; + + /* 36.322 5.2.2.3 says: + * + * - include a poll in a RLC data PDU as described in section 5.2.2.1 + * + * That does not seem to be conditional. So we forcefully will send + * a poll as soon as we generate a PDU. + * Hopefully this interpretation is correct. In the worst case we generate + * more polling than necessary, but it's not a big deal. When + * 't_poll_retransmit' expires it means we didn't receive a status report, + * meaning a bad radio link, so things are quite bad at this point and + * asking again for a poll won't hurt much more. + */ + entity->force_poll = 1; + + LOG_D(RLC, "%s:%d:%s: warning: t_poll_retransmit expired\n", + __FILE__, __LINE__, __FUNCTION__); + + /* do we meet conditions of 36.322 5.2.2.3? */ + if (!check_poll_after_pdu_assembly(entity)) + return; + + /* search wait list for PDU with SN = VT(S)-1 */ + sn = (entity->vt_s + 1023) % 1024; + + head.next = entity->wait_list; + cur = entity->wait_list; + prev = &head; + + while (cur != NULL) { + if (cur->sn == sn) + break; + prev = cur; + cur = cur->next; + } + + /* PDU with SN = VT(S)-1 not found?, take the head of wait list */ + if (cur == NULL) { + cur = entity->wait_list; + prev = &head; + sn = cur->sn; + } + + /* 36.322 says "PDU", not "PDU segment", so let's retransmit all + * PDU segments with this SN + */ + while (cur != NULL && cur->sn == sn) { + prev->next = cur->next; + entity->wait_list = head.next; + /* put in retransmit list */ + consider_retransmission(entity, cur); + cur = prev->next; + } +} + +static void check_t_reordering(rlc_entity_am_t *entity) +{ + int sn; + + /* is t_reordering running and if yes has it expired? */ + if (entity->t_reordering_start == 0 || + entity->t_current <= entity->t_reordering_start + entity->t_reordering) + return; + + /* stop timer */ + entity->t_reordering_start = 0; + + LOG_D(RLC, "%s:%d:%s: t_reordering expired\n", __FILE__, __LINE__, __FUNCTION__); + + /* update VR(MS) to first SN >= VR(X) for which not all PDU segments + * have been received + */ + sn = entity->vr_x; + while (rlc_am_segment_full(entity, sn)) + sn = (sn + 1) % 1024; + entity->vr_ms = sn; + + if (sn_compare_rx(entity, entity->vr_h, entity->vr_ms) > 0) { + entity->t_reordering_start = entity->t_current; + entity->vr_x = entity->vr_h; + } + + /* trigger STATUS report */ + entity->status_triggered = 1; +} + +void rlc_entity_am_set_time(rlc_entity_t *_entity, uint64_t now) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + + entity->t_current = now; + + check_t_poll_retransmit(entity); + + check_t_reordering(entity); + + /* t_status_prohibit is handled by generate_status */ +} + +/*************************************************************************/ +/* discard/re-establishment/delete */ +/*************************************************************************/ + +void rlc_entity_am_discard_sdu(rlc_entity_t *_entity, int sdu_id) +{ + /* implements 36.322 5.3 */ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + rlc_sdu_t head; + rlc_sdu_t *cur; + rlc_sdu_t *prev; + + head.next = entity->tx_list; + cur = entity->tx_list; + prev = &head; + + while (cur != NULL && cur->upper_layer_id != sdu_id) { + prev = cur; + cur = cur->next; + } + + /* if sdu_id not found or some bytes have already been 'PDU-ized' + * then do nothing + */ + if (cur == NULL || cur->next_byte != 0) + return; + + /* remove SDU from tx_list */ + prev->next = cur->next; + entity->tx_list = head.next; + if (entity->tx_end == cur) { + if (prev != &head) + entity->tx_end = prev; + else + entity->tx_end = NULL; + } + + rlc_free_sdu(cur); +} + +static void free_pdu_segment_list(rlc_tx_pdu_segment_t *l) +{ + rlc_tx_pdu_segment_t *cur; + + while (l != NULL) { + cur = l; + l = l->next; + rlc_tx_free_pdu(cur); + } +} + +static void clear_entity(rlc_entity_am_t *entity) +{ + rlc_rx_pdu_segment_t *cur_rx; + rlc_sdu_t *cur_tx; + + entity->vr_r = 0; + entity->vr_x = 0; + entity->vr_ms = 0; + entity->vr_h = 0; + + entity->status_triggered = 0; + + entity->vt_a = 0; + entity->vt_s = 0; + entity->poll_sn = 0; + entity->pdu_without_poll = 0; + entity->byte_without_poll = 0; + entity->force_poll = 0; + + entity->t_current = 0; + + entity->t_reordering_start = 0; + entity->t_status_prohibit_start = 0; + entity->t_poll_retransmit_start = 0; + + cur_rx = entity->rx_list; + while (cur_rx != NULL) { + rlc_rx_pdu_segment_t *p = cur_rx; + cur_rx = cur_rx->next; + rlc_rx_free_pdu_segment(p); + } + entity->rx_list = NULL; + entity->rx_size = 0; + + memset(&entity->reassemble, 0, sizeof(rlc_am_reassemble_t)); + + cur_tx = entity->tx_list; + while (cur_tx != NULL) { + rlc_sdu_t *p = cur_tx; + cur_tx = cur_tx->next; + rlc_free_sdu(p); + } + entity->tx_list = NULL; + entity->tx_end = NULL; + entity->tx_size = 0; + + free_pdu_segment_list(entity->wait_list); + free_pdu_segment_list(entity->retransmit_list); + free_pdu_segment_list(entity->ack_list); + entity->wait_list = NULL; + entity->retransmit_list = NULL; + entity->ack_list = NULL; +} + +void rlc_entity_am_reestablishment(rlc_entity_t *_entity) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + + /* 36.322 5.4 says to deliver SDUs if possible. + * Let's not do that, it makes the code simpler. + * TODO: change this behavior if wanted/needed. + */ + + clear_entity(entity); +} + +void rlc_entity_am_delete(rlc_entity_t *_entity) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + clear_entity(entity); + free(entity); +} diff --git a/openair2/LAYER2/rlc_v2/rlc_entity_am.h b/openair2/LAYER2/rlc_v2/rlc_entity_am.h new file mode 100644 index 0000000000..0437f17ad8 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity_am.h @@ -0,0 +1,285 @@ +/* + * 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 _RLC_ENTITY_AM_H_ +#define _RLC_ENTITY_AM_H_ + +#include + +#include "rlc_entity.h" +#include "rlc_pdu.h" +#include "rlc_sdu.h" + +/* + * Here comes some documentation to understand the reassembly + * logic in the code and the fields in the structure rlc_am_reassemble_t. + * + * Inside RLC, we deal with SDUs, PDUs and PDU segments. + * SDUs are packets coming from upper layer. + * A PDU is made of a header and a payload. + * In the payload there are SDUs. + * First SDU and last SDU in a PDU may be incomplete. + * PDU segments exist in case of retransmissions when the MAC + * layer asks for less data than previously, in which case + * only part of the previous PDU is sent. + * + * This is PDU data (just bytes): + * --------------------------------------------------------- + * | PDU data | + * --------------------------------------------------------- + * It contains SDUs, like: + * --------------------------------------------------------- + * | SDU 1 | SDU 2 | [...] | SDU n | + * --------------------------------------------------------- + * SDU 1 may be only the end of an SDU from which previous bytes were + * transmitted in previous PDUs. + * SDU n may be only the start of an SDU, that is more bytes from + * this SDU may be sent in successive PDUs. + * + * At front of the PDU data, we have a header: + * --------------- --------------------------------------------------------- + * | PDU header | | SDU 1 | SDU 2 | [...] | SDU n | + * --------------- --------------------------------------------------------- + * PDU header describes PDU data (most notably lengths). + * + * A PDU segment is a part of a PDU. For example, from this PDU data: + * --------------------------------------------------------- + * | SDU 1 | SDU 2 | [...] | SDU n | + * --------------------------------------------------------- + * We can extract the following PDU segment (data part only): + * ---------------------- + * | PDU segment data | + * ---------------------- + * This PDU segment would contain the end of SDU 2 above and some SDUs up to, + * let's say SDU x (x is 5 below). + * + * In front of a transmitted PDU segment, we have a header, + * containing the important variable 'so' (segment offset) that gives + * the index of the first byte of the segment in the original PDU. + * -------------- ---------------------- + * | seg. header| | PDU segment data | + * -------------- ---------------------- + * + * Let's now explain the data structure rlc_am_reassemble_t. + * + * In the structure rlc_am_reassemble_t, the fields fi, e, sn and so + * are coming from the PDU segment header and the semantics is the + * one of the RLC specs. + * + * The currently processed PDU segment is stored in 'start'. + * We have 'start->s->data_offset' and 'start->s->size'. + * start->s->data_offset is the index of the start of the data in the + * PDU segment. That is if the header is of length 3 bytes + * then start->s->data_offset is 3. + * start->s->size is the total length of the PDU segment, + * including header. + * The size of actual data bytes in the PDU segment is thus + * start->s->size - start->s->data_offset. + * + * The field sdu_len is the length of the current SDU being + * processed. + * + * The field sdu_offset is the starting point of the + * current SDU being processed (starting from beginning + * of PDU segment, including header). + * + * The field data_pos is the current read pointer. 0 points to + * the beginning of the PDU segment (including header). + * + * The field pdu_byte points to the current byte in the original + * PDU (not the PDU segment). It starts at 0 when we start + * processing a new PDU (when a new 'sn' is seen) and always + * increases after each byte processed. This is tha variable + * that is used to know if the next PDU segment will be used + * or not and if yes, starting from which data byte (see + * function rlc_am_reassemble_next_segment). + * + * 'so' is important and points to the byte in the original PDU + * that is the first byte of the PDU segment. + * + * For example, let's take this PDU segment data from above: + * ---------------------- + * | PDU segment data | + * ---------------------- + * Let's say it is decomposed as: + * ---------------------- + * |222|33|4444|55555555| + * ---------------------- + * It contains SDUs 2, 3, 4, and 5. + * SDU 2 is 3 bytes, SDU 3 is 2 bytes, SDU 4 is 4 bytes, SDU 5 is 8 bytes. + * + * Let's suppose that the original PDU starts with: + * ---------------- + * |1111111|222222| + * ---------------- + * + * (In this example, in the PDU segment, SDU 2 is not full, + * we only have its end.) + * + * Then 'so' is 13 (SDU 1 is 7 bytes, head of SDU 2 is 6 bytes). + * + * Let's continue with our PDU segment data. + * Let's say we are current processing SDU 4. + * Let's say the read pointer (variable 'data_pos') is there: + * ---------------------- + * |222|33|4444|55555555| + * ---------------------- + * ^ + * read pointer (data_pos) + * + * Then: + * - sdu_len is 4 + * - sdu_offset is 5 + [PDU segment header length] + * (it points to the beginning of SDU 4, starting + * from the head of the PDU segment, that is + * 3 bytes for SDU 2, 2 bytes for SDU 3, and the + * PDU segment header length) + * - start->s->data_offset is [PDU segment header length] + * - pdu_byte is 20 + * (13 bytes from beginning of original PDU, + * 3 bytes for SDU 2, 2 bytes for SDU 3, then 2 bytes for SDU 4) + * - data_pos = read pointer = 7 + [PDU segment header length] + * + * To finish this description, in the code, a PDU is simply + * seen as a PDU segment with 'so' = 0 (and is_last == 1 (lsf in the specs), + * but this variable is not used by the reassembly logic). + * + * And for [PDU segment header length] we use start->s->data_offset. + * + * To recap, here is an illustration of the various variables + * and what starting point they use. In the figures, the start + * of the variable name is aligned to the byte it refers to. + * + is used to show the starting point. + * + * Let's put the PDU segment back into the original PDU. + * And let's show the values for when the read pointer + * is on the second byte of SDU 4 (as above). + * + * +++++++++++++++ so + * +++++++++++++++++++++++ pdu_byte + * --------------------------------------------------------- + * | SDU 1| SDU 2..222|33|4444|55555555| [...] | SDU n | + * --------------------------------------------------------- + * + * And now the PDU segment with header. + * + * + * ++++ sdu_len + * ++++++++++++++++++++++ sdu_offset + * +++++++++++++++++++++++ data_pos + * +++++++++++++++ start->s->data_offset + * +++++++++++++++++++++++++++++++++++++ start->s->size + * -------------- ---------------------- + * | seg. header| |222|33|4444|55555555| + * -------------- ---------------------- + * + * We see three case for the starting point: + * - start of original PDU (without any header) + * - start of header of current PDU segment + * - start of current SDU (for sdu_len) + */ + +typedef struct { + rlc_rx_pdu_segment_t *start; /* start of list */ + rlc_rx_pdu_segment_t *end; /* end of list (last element) */ + int pos; /* byte to get from current buffer */ + char sdu[SDU_MAX]; /* sdu is reassembled here */ + int sdu_pos; /* next byte to put in sdu */ + + /* decoder of current PDU */ + rlc_pdu_decoder_t dec; + int fi; + int e; + int sn; + int so; + int sdu_len; + int sdu_offset; + int data_pos; + int pdu_byte; +} rlc_am_reassemble_t; + +typedef struct { + rlc_entity_t common; + + /* configuration */ + int t_reordering; + int t_status_prohibit; + int t_poll_retransmit; + int poll_pdu; /* -1 means infinity */ + int poll_byte; /* -1 means infinity */ + int max_retx_threshold; + + /* runtime rx */ + int vr_r; + int vr_x; + int vr_ms; + int vr_h; + + int status_triggered; + + /* runtime tx */ + int vt_a; + int vt_s; + int poll_sn; + int pdu_without_poll; + int byte_without_poll; + int force_poll; + + /* set to the latest know time by the user of the module. Unit: ms */ + uint64_t t_current; + + /* timers (stores the TTI of activation, 0 means not active) */ + uint64_t t_reordering_start; + uint64_t t_status_prohibit_start; + uint64_t t_poll_retransmit_start; + + /* rx management */ + rlc_rx_pdu_segment_t *rx_list; + int rx_size; + int rx_maxsize; + + /* reassembly management */ + rlc_am_reassemble_t reassemble; + + /* tx management */ + rlc_sdu_t *tx_list; + rlc_sdu_t *tx_end; + int tx_size; + int tx_maxsize; + + rlc_tx_pdu_segment_t *wait_list; + rlc_tx_pdu_segment_t *retransmit_list; + + rlc_tx_pdu_segment_t *ack_list; +} rlc_entity_am_t; + +void rlc_entity_am_recv_sdu(rlc_entity_t *entity, char *buffer, int size, + int sdu_id); +void rlc_entity_am_recv_pdu(rlc_entity_t *entity, char *buffer, int size); +rlc_entity_buffer_status_t rlc_entity_am_buffer_status( + rlc_entity_t *entity, int maxsize); +int rlc_entity_am_generate_pdu(rlc_entity_t *entity, char *buffer, int size); +void rlc_entity_am_set_time(rlc_entity_t *entity, uint64_t now); +void rlc_entity_am_discard_sdu(rlc_entity_t *entity, int sdu_id); +void rlc_entity_am_reestablishment(rlc_entity_t *entity); +void rlc_entity_am_delete(rlc_entity_t *entity); + +#endif /* _RLC_ENTITY_AM_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_entity_um.c b/openair2/LAYER2/rlc_v2/rlc_entity_um.c new file mode 100644 index 0000000000..54707875a0 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity_um.c @@ -0,0 +1,708 @@ +/* + * 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 "rlc_entity_um.h" +#include "rlc_pdu.h" + +#include +#include + +#include "LOG/log.h" + +/*************************************************************************/ +/* PDU RX functions */ +/*************************************************************************/ + +static int modulus_rx(rlc_entity_um_t *entity, int a) +{ + /* as per 36.322 7.1, modulus base is vr(uh)-window_size and modulus is + * 2^sn_field_length (which is 'sn_modulus' in rlc_entity_um_t) + */ + int r = a - (entity->vr_uh - entity->window_size); + if (r < 0) r += entity->sn_modulus; + return r % entity->sn_modulus; +} + +static int sn_compare_rx(void *_entity, int a, int b) +{ + rlc_entity_um_t *entity = _entity; + return modulus_rx(entity, a) - modulus_rx(entity, b); +} + +static int sn_in_recv_window(void *_entity, int sn) +{ + rlc_entity_um_t *entity = _entity; + int mod_sn = modulus_rx(entity, sn); + /* we simplify (VR(UH) - UM_Window_Size) <= SN < VR(UH), base is + * (VR(UH) - UM_Window_Size) and VR(UH) = base + window_size + */ + return mod_sn < entity->window_size; +} + +/* return 1 if a PDU with SN == 'sn' is in the rx list, 0 otherwise */ +static int rlc_um_pdu_received(rlc_entity_um_t *entity, int sn) +{ + rlc_rx_pdu_segment_t *cur = entity->rx_list; + while (cur != NULL) { + if (cur->sn == sn) + return 1; + cur = cur->next; + } + return 0; +} + +static int less_than_vr_ur(rlc_entity_um_t *entity, int sn) +{ + return sn_compare_rx(entity, sn, entity->vr_ur) < 0; +} + +static int outside_of_reordering_window(rlc_entity_um_t *entity, int sn) +{ + return !sn_in_recv_window(entity, sn); +} + +static int less_than_vr_uh(rlc_entity_um_t *entity, int sn) +{ + return sn_compare_rx(entity, sn, entity->vr_uh) < 0; +} + +static void rlc_um_reassemble_pdu(rlc_entity_um_t *entity, + rlc_rx_pdu_segment_t *pdu) +{ + rlc_um_reassemble_t *r = &entity->reassemble; + + int fi; + int e; + int sn; + int data_pos; + int sdu_len; + int sdu_offset; + + sdu_offset = pdu->data_offset; + + rlc_pdu_decoder_init(&r->dec, pdu->data, pdu->size); + + if (entity->sn_field_length == 10) + rlc_pdu_decoder_get_bits(&r->dec, 3); + + fi = rlc_pdu_decoder_get_bits(&r->dec, 2); + e = rlc_pdu_decoder_get_bits(&r->dec, 1); + sn = rlc_pdu_decoder_get_bits(&r->dec, entity->sn_field_length); + + if (e) { + e = rlc_pdu_decoder_get_bits(&r->dec, 1); + sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else + sdu_len = pdu->size - sdu_offset; + + /* discard current SDU being reassembled if bad SN or bad FI */ + if (sn != (r->sn + 1) % entity->sn_modulus || + !(fi & 0x02)) { + if (r->sdu_pos) + LOG_D(RLC, "%s:%d:%s: warning: discard partially reassembled SDU\n", + __FILE__, __LINE__, __FUNCTION__); + r->sdu_pos = 0; + } + + /* if the head of the SDU is missing, still process the PDU + * but remember to discard the reassembled SDU later on (the + * head has not been received). + * The head is missing if sdu_pos == 0 and fi says the PDU does not + * start an SDU. + */ + if (r->sdu_pos == 0 && (fi & 0x02)) + r->sdu_head_missing = 1; + + r->sn = sn; + data_pos = pdu->data_offset; + + while (1) { + if (r->sdu_pos >= SDU_MAX) { + /* TODO: proper error handling (discard PDUs with current sn from + * reassembly queue? something else?) + */ + LOG_E(RLC, "%s:%d:%s: bad RLC PDU\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + r->sdu[r->sdu_pos] = pdu->data[data_pos]; + r->sdu_pos++; + data_pos++; + if (data_pos == sdu_offset + sdu_len) { + /* all bytes of SDU are consumed, check if SDU is fully there. + * It is if the data pointer is not at the end of the PDU segment + * or if 'fi' & 1 == 0 + */ + if (data_pos != pdu->size || (fi & 1) == 0) { + /* time to discard the SDU if we didn't receive the head */ + if (r->sdu_head_missing) { + LOG_D(RLC, "%s:%d:%s: warning: discard SDU, head not received\n", + __FILE__, __LINE__, __FUNCTION__); + r->sdu_head_missing = 0; + } else { + /* SDU is full - deliver to higher layer */ + entity->common.deliver_sdu(entity->common.deliver_sdu_data, + (rlc_entity_t *)entity, + r->sdu, r->sdu_pos); + } + r->sdu_pos = 0; + } + /* done with PDU? */ + if (data_pos == pdu->size) + break; + /* not at the end of PDU, process next SDU */ + sdu_offset += sdu_len; + if (e) { + e = rlc_pdu_decoder_get_bits(&r->dec, 1); + sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else + sdu_len = pdu->size - sdu_offset; + } + } +} + +static void rlc_um_reassemble(rlc_entity_um_t *entity, + int (*check_sn)(rlc_entity_um_t *entity, int sn)) +{ + rlc_rx_pdu_segment_t *cur; + + /* process all PDUs from head of rx list until all is processed or + * the SN is not valid anymore with respect to 'check_sn' + */ + while (entity->rx_list != NULL && check_sn(entity, entity->rx_list->sn)) { + cur = entity->rx_list; + rlc_um_reassemble_pdu(entity, cur); + entity->rx_size -= cur->size; + entity->rx_list = cur->next; + rlc_rx_free_pdu_segment(cur); + } +} + +static void rlc_um_reception_actions(rlc_entity_um_t *entity, + rlc_rx_pdu_segment_t *pdu_segment) +{ + if (!sn_in_recv_window(entity, pdu_segment->sn)) { + entity->vr_uh = (pdu_segment->sn + 1) % entity->sn_modulus; + rlc_um_reassemble(entity, outside_of_reordering_window); + if (!sn_in_recv_window(entity, entity->vr_ur)) + entity->vr_ur = (entity->vr_uh - entity->window_size + + entity->sn_modulus) % entity->sn_modulus; + } + + if (rlc_um_pdu_received(entity, entity->vr_ur)) { + do { + entity->vr_ur = (entity->vr_ur + 1) % entity->sn_modulus; + } while (rlc_um_pdu_received(entity, entity->vr_ur)); + rlc_um_reassemble(entity, less_than_vr_ur); + } + + if (entity->t_reordering_start) { + if (sn_compare_rx(entity, entity->vr_ux, entity->vr_ur) <= 0 || + (!sn_in_recv_window(entity, entity->vr_ux) && + entity->vr_ux != entity->vr_uh)) + entity->t_reordering_start = 0; + } + + if (entity->t_reordering_start == 0) { + if (sn_compare_rx(entity, entity->vr_uh, entity->vr_ur) > 0) { + entity->t_reordering_start = entity->t_current; + entity->vr_ux = entity->vr_uh; + } + } +} + +void rlc_entity_um_recv_pdu(rlc_entity_t *_entity, char *buffer, int size) +{ +#define R(d) do { if (rlc_pdu_decoder_in_error(&d)) goto err; } while (0) + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + rlc_pdu_decoder_t decoder; + rlc_pdu_decoder_t data_decoder; + + int e; + int sn; + + int data_e; + int data_li; + + int packet_count; + int data_size; + int data_start; + int indicated_data_size; + + rlc_rx_pdu_segment_t *pdu_segment; + + rlc_pdu_decoder_init(&decoder, buffer, size); + + if (entity->sn_field_length == 10) { + rlc_pdu_decoder_get_bits(&decoder, 3); R(decoder); /* R1 */ + } + + rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder); /* FI */ + e = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + sn = rlc_pdu_decoder_get_bits(&decoder, entity->sn_field_length); R(decoder); + + /* dicard PDU if rx buffer is full */ + if (entity->rx_size + size > entity->rx_maxsize) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, RX buffer full\n", + __FILE__, __LINE__, __FUNCTION__); + return; + } + + /* discard according to 36.322 5.1.2.2.2 */ + if ((sn_compare_rx(entity, entity->vr_ur, sn) < 0 && + sn_compare_rx(entity, sn, entity->vr_uh) < 0 && + rlc_um_pdu_received(entity, sn)) || + (sn_compare_rx(entity, entity->vr_uh - entity->window_size, sn) <= 0 && + sn_compare_rx(entity, sn, entity->vr_ur) < 0)) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU (sn %d vr(ur) %d vr(uh) %d)\n", + __FILE__, __LINE__, __FUNCTION__, + sn, entity->vr_ur, entity->vr_uh); + return; + } + + packet_count = 1; + + /* go to start of data */ + indicated_data_size = 0; + data_decoder = decoder; + data_e = e; + while (data_e) { + data_e = rlc_pdu_decoder_get_bits(&data_decoder, 1); R(data_decoder); + data_li = rlc_pdu_decoder_get_bits(&data_decoder, 11); R(data_decoder); + if (data_li == 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, li == 0\n", + __FILE__, __LINE__, __FUNCTION__); + return; + } + indicated_data_size += data_li; + packet_count++; + } + rlc_pdu_decoder_align(&data_decoder); + + data_start = data_decoder.byte; + data_size = size - data_start; + + if (data_size <= 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, wrong data size (sum of LI %d data size %d)\n", + __FILE__, __LINE__, __FUNCTION__, + indicated_data_size, data_size); + return; + } + if (indicated_data_size >= data_size) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, bad LIs (sum of LI %d data size %d)\n", + __FILE__, __LINE__, __FUNCTION__, + indicated_data_size, data_size); + return; + } + + /* put in pdu reception list */ + entity->rx_size += size; + pdu_segment = rlc_rx_new_pdu_segment(sn, 0, size, 1, buffer, data_start); + entity->rx_list = rlc_rx_pdu_segment_list_add(sn_compare_rx, entity, + entity->rx_list, pdu_segment); + + /* do reception actions (36.322 5.1.2.2.3) */ + rlc_um_reception_actions(entity, pdu_segment); + + return; + +err: + LOG_D(RLC, "%s:%d:%s: error decoding PDU, discarding\n", __FILE__, __LINE__, __FUNCTION__); + +#undef R +} + +/*************************************************************************/ +/* TX functions */ +/*************************************************************************/ + +typedef struct { + int sdu_count; + int data_size; + int header_size; + int last_sdu_is_full; + int first_sdu_length; +} tx_pdu_size_t; + +static int header_size(int sn_field_length, int sdu_count) +{ + int bits = 8 + 8 * (sn_field_length == 10) + 12 * (sdu_count - 1); + /* padding if we have to */ + return (bits + 7) / 8; +} + +static tx_pdu_size_t tx_pdu_size(rlc_entity_um_t *entity, int maxsize) +{ + tx_pdu_size_t ret; + int sdu_count; + int sdu_size; + int pdu_data_size; + rlc_sdu_t *sdu; + + ret.sdu_count = 0; + ret.data_size = 0; + ret.header_size = 0; + ret.last_sdu_is_full = 1; + ret.first_sdu_length = 0; + + /* TX PDU - let's make the biggest PDU we can with the SDUs we have */ + sdu_count = 0; + pdu_data_size = 0; + sdu = entity->tx_list; + while (sdu != NULL) { + int new_header_size = header_size(entity->sn_field_length, sdu_count+1); + /* if we cannot put new header + at least 1 byte of data then over */ + if (new_header_size + pdu_data_size >= maxsize) + break; + sdu_count++; + /* only include the bytes of this SDU not included in PDUs already */ + sdu_size = sdu->size - sdu->next_byte; + /* don't feed more than 'maxsize' bytes */ + if (new_header_size + pdu_data_size + sdu_size > maxsize) { + sdu_size = maxsize - new_header_size - pdu_data_size; + ret.last_sdu_is_full = 0; + } + if (sdu_count == 1) + ret.first_sdu_length = sdu_size; + pdu_data_size += sdu_size; + /* if we put more than 2^11-1 bytes then the LI field cannot be used, + * so this is the last SDU we can put + */ + if (sdu_size > 2047) + break; + sdu = sdu->next; + } + + if (sdu_count) { + ret.sdu_count = sdu_count; + ret.data_size = pdu_data_size; + ret.header_size = header_size(entity->sn_field_length, sdu_count); + } + + return ret; +} + +rlc_entity_buffer_status_t rlc_entity_um_buffer_status( + rlc_entity_t *_entity, int maxsize) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + rlc_entity_buffer_status_t ret; + tx_pdu_size_t tx_size; + + ret.status_size = 0; + + /* todo: if an SDU has size >2047 in the tx list then processing + * stops and computed size will not be accurate. Change the computation + * to be more accurate (if needed). + */ + tx_size = tx_pdu_size(entity, maxsize); + ret.tx_size = tx_size.data_size + tx_size.header_size; + + ret.retx_size = 0; + + return ret; +} + +int rlc_entity_um_generate_pdu(rlc_entity_t *_entity, char *buffer, int size) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + tx_pdu_size_t pdu_size; + rlc_sdu_t *sdu; + int i; + int cursize; + int first_sdu_full; + int last_sdu_full; + rlc_pdu_encoder_t encoder; + int fi; + int e; + int li; + char *out; + int outpos; + int first_sdu_start_byte; + int sdu_start_byte; + + pdu_size = tx_pdu_size(entity, size); + if (pdu_size.sdu_count == 0) + return 0; + + sdu = entity->tx_list; + + first_sdu_start_byte = sdu->next_byte; + + /* reserve SDU bytes */ + cursize = 0; + for (i = 0; i < pdu_size.sdu_count; i++, sdu = sdu->next) { + int sdu_size = sdu->size - sdu->next_byte; + if (cursize + sdu_size > pdu_size.data_size) + sdu_size = pdu_size.data_size - cursize; + sdu->next_byte += sdu_size; + cursize += sdu_size; + } + + first_sdu_full = first_sdu_start_byte == 0; + last_sdu_full = pdu_size.last_sdu_is_full; + + /* generate header */ + rlc_pdu_encoder_init(&encoder, buffer, size); + + if (entity->sn_field_length == 10) + rlc_pdu_encoder_put_bits(&encoder, 0, 3); /* R1 */ + + fi = 0; + if (!first_sdu_full) + fi |= 0x02; + if (!last_sdu_full) + fi |= 0x01; + rlc_pdu_encoder_put_bits(&encoder, fi, 2); /* FI */ + + /* see the AM code to understand the logic for Es and LIs */ + if (pdu_size.sdu_count >= 2) + e = 1; + else + e = 0; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + + if (entity->sn_field_length == 10) + rlc_pdu_encoder_put_bits(&encoder, entity->vt_us, 10); /* SN */ + else + rlc_pdu_encoder_put_bits(&encoder, entity->vt_us, 5); /* SN */ + + /* put LIs */ + sdu = entity->tx_list; + /* first SDU */ + li = pdu_size.first_sdu_length; + /* put E+LI only if at least 2 SDUs */ + if (pdu_size.sdu_count >= 2) { + /* E is 1 if at least 3 SDUs */ + if (pdu_size.sdu_count >= 3) + e = 1; + else + e = 0; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */ + } + /* next SDUs, but not the last (no LI for the last) */ + sdu = sdu->next; + for (i = 2; i < pdu_size.sdu_count; i++, sdu = sdu->next) { + if (i != pdu_size.sdu_count - 1) + e = 1; + else + e = 0; + li = sdu->size; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */ + } + + rlc_pdu_encoder_align(&encoder); + + /* generate data */ + out = buffer + pdu_size.header_size; + sdu = entity->tx_list; + sdu_start_byte = first_sdu_start_byte; + outpos = 0; + for (i = 0; i < pdu_size.sdu_count; i++, sdu = sdu->next) { + li = sdu->size - sdu_start_byte; + if (outpos + li >= pdu_size.data_size) + li = pdu_size.data_size - outpos; + memcpy(out+outpos, sdu->data + sdu_start_byte, li); + outpos += li; + sdu_start_byte = 0; + } + + /* cleanup sdu list */ + while (entity->tx_list != NULL && + entity->tx_list->size == entity->tx_list->next_byte) { + rlc_sdu_t *c = entity->tx_list; + /* release SDU bytes */ + entity->tx_size -= c->size; + entity->tx_list = c->next; + rlc_free_sdu(c); + } + if (entity->tx_list == NULL) + entity->tx_end = NULL; + + /* update VT(US) */ + entity->vt_us = (entity->vt_us + 1) % entity->sn_modulus; + + return pdu_size.header_size + pdu_size.data_size; +} + +/*************************************************************************/ +/* SDU RX functions */ +/*************************************************************************/ + +void rlc_entity_um_recv_sdu(rlc_entity_t *_entity, char *buffer, int size, + int sdu_id) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + rlc_sdu_t *sdu; + + if (size > SDU_MAX) { + LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n", + __FILE__, __LINE__, __FUNCTION__, size); + exit(1); + } + + if (entity->tx_size + size > entity->tx_maxsize) { + LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n", + __FILE__, __LINE__, __FUNCTION__); + return; + } + + entity->tx_size += size; + + sdu = rlc_new_sdu(buffer, size, sdu_id); + rlc_sdu_list_add(&entity->tx_list, &entity->tx_end, sdu); +} + +/*************************************************************************/ +/* time/timers */ +/*************************************************************************/ + +static void check_t_reordering(rlc_entity_um_t *entity) +{ + int sn; + + /* is t_reordering running and if yes has it expired? */ + if (entity->t_reordering_start == 0 || + entity->t_current <= entity->t_reordering_start + entity->t_reordering) + return; + + /* stop timer */ + entity->t_reordering_start = 0; + + LOG_D(RLC, "%s:%d:%s: t_reordering expired\n", __FILE__, __LINE__, __FUNCTION__); + + /* update VR(UR) to first SN >= VR(UX) of PDU not received + */ + sn = entity->vr_ux; + while (rlc_um_pdu_received(entity, sn)) + sn = (sn + 1) % entity->sn_modulus; + entity->vr_ur = sn; + + rlc_um_reassemble(entity, less_than_vr_ur); + + if (sn_compare_rx(entity, entity->vr_uh, entity->vr_ur) > 0) { + entity->t_reordering_start = entity->t_current; + entity->vr_ux = entity->vr_uh; + } +} + +void rlc_entity_um_set_time(rlc_entity_t *_entity, uint64_t now) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + + entity->t_current = now; + + check_t_reordering(entity); +} + +/*************************************************************************/ +/* discard/re-establishment/delete */ +/*************************************************************************/ + +void rlc_entity_um_discard_sdu(rlc_entity_t *_entity, int sdu_id) +{ + /* implements 36.322 5.3 */ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + rlc_sdu_t head; + rlc_sdu_t *cur; + rlc_sdu_t *prev; + + head.next = entity->tx_list; + cur = entity->tx_list; + prev = &head; + + while (cur != NULL && cur->upper_layer_id != sdu_id) { + prev = cur; + cur = cur->next; + } + + /* if sdu_id not found or some bytes have already been 'PDU-ized' + * then do nothing + */ + if (cur == NULL || cur->next_byte != 0) + return; + + /* remove SDU from tx_list */ + prev->next = cur->next; + entity->tx_list = head.next; + if (entity->tx_end == cur) { + if (prev != &head) + entity->tx_end = prev; + else + entity->tx_end = NULL; + } + + rlc_free_sdu(cur); +} + +static void clear_entity(rlc_entity_um_t *entity) +{ + rlc_rx_pdu_segment_t *cur_rx; + rlc_sdu_t *cur_tx; + + entity->vr_ur = 0; + entity->vr_ux = 0; + entity->vr_uh = 0; + + entity->vt_us = 0; + + entity->t_current = 0; + + entity->t_reordering_start = 0; + + cur_rx = entity->rx_list; + while (cur_rx != NULL) { + rlc_rx_pdu_segment_t *p = cur_rx; + cur_rx = cur_rx->next; + rlc_rx_free_pdu_segment(p); + } + entity->rx_list = NULL; + entity->rx_size = 0; + + memset(&entity->reassemble, 0, sizeof(rlc_um_reassemble_t)); + + cur_tx = entity->tx_list; + while (cur_tx != NULL) { + rlc_sdu_t *p = cur_tx; + cur_tx = cur_tx->next; + rlc_free_sdu(p); + } + entity->tx_list = NULL; + entity->tx_end = NULL; + entity->tx_size = 0; +} + +void rlc_entity_um_reestablishment(rlc_entity_t *_entity) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + + rlc_um_reassemble(entity, less_than_vr_uh); + + clear_entity(entity); +} + +void rlc_entity_um_delete(rlc_entity_t *_entity) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + clear_entity(entity); + free(entity); +} diff --git a/openair2/LAYER2/rlc_v2/rlc_entity_um.h b/openair2/LAYER2/rlc_v2/rlc_entity_um.h new file mode 100644 index 0000000000..02c5141a7a --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity_um.h @@ -0,0 +1,90 @@ +/* + * 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 _RLC_ENTITY_UM_H_ +#define _RLC_ENTITY_UM_H_ + +#include "rlc_entity.h" +#include "rlc_pdu.h" +#include "rlc_sdu.h" + +typedef struct { + char sdu[SDU_MAX]; /* sdu is reassembled here */ + int sdu_pos; /* next byte to put in sdu */ + + /* decoder of current PDU */ + rlc_pdu_decoder_t dec; + int sn; + + int sdu_head_missing; +} rlc_um_reassemble_t; + +typedef struct { + rlc_entity_t common; + + /* configuration */ + int t_reordering; + int sn_field_length; + + int sn_modulus; /* 1024 for sn_field_length == 10, 32 for 5 */ + int window_size; /* 512 for sn_field_length == 10, 16 for 5 */ + + /* runtime rx */ + int vr_ur; + int vr_ux; + int vr_uh; + + /* runtime tx */ + int vt_us; + + /* set to the latest know time by the user of the module. Unit: ms */ + uint64_t t_current; + + /* timers (stores the TTI of activation, 0 means not active) */ + uint64_t t_reordering_start; + + /* rx management */ + rlc_rx_pdu_segment_t *rx_list; + int rx_size; + int rx_maxsize; + + /* reassembly management */ + rlc_um_reassemble_t reassemble; + + /* tx management */ + rlc_sdu_t *tx_list; + rlc_sdu_t *tx_end; + int tx_size; + int tx_maxsize; +} rlc_entity_um_t; + +void rlc_entity_um_recv_sdu(rlc_entity_t *_entity, char *buffer, int size, + int sdu_id); +void rlc_entity_um_recv_pdu(rlc_entity_t *entity, char *buffer, int size); +rlc_entity_buffer_status_t rlc_entity_um_buffer_status( + rlc_entity_t *entity, int maxsize); +int rlc_entity_um_generate_pdu(rlc_entity_t *_entity, char *buffer, int size); +void rlc_entity_um_set_time(rlc_entity_t *entity, uint64_t now); +void rlc_entity_um_discard_sdu(rlc_entity_t *entity, int sdu_id); +void rlc_entity_um_reestablishment(rlc_entity_t *entity); +void rlc_entity_um_delete(rlc_entity_t *entity); + +#endif /* _RLC_ENTITY_UM_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_oai_api.c b/openair2/LAYER2/rlc_v2/rlc_oai_api.c new file mode 100644 index 0000000000..bd3eebe635 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_oai_api.c @@ -0,0 +1,1030 @@ +/* + * 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 + */ + +/* from openair */ +#include "rlc.h" +#include "pdcp.h" + +/* from new rlc module */ +#include "asn1_utils.h" +#include "rlc_ue_manager.h" +#include "rlc_entity.h" + +#include + +static rlc_ue_manager_t *rlc_ue_manager; + +/* TODO: handle time a bit more properly */ +static uint64_t rlc_current_time; +static int rlc_current_time_last_frame; +static int rlc_current_time_last_subframe; + +void mac_rlc_data_ind ( + const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const eNB_flag_t enb_flagP, + const MBMS_flag_t MBMS_flagP, + const logical_chan_id_t channel_idP, + char *buffer_pP, + const tb_size_t tb_sizeP, + num_tb_t num_tbP, + crc_t *crcs_pP) +{ + rlc_ue_t *ue; + rlc_entity_t *rb; + int rnti; + int channel_id; + + if (enb_flagP == 1 && module_idP != 0) { + LOG_E(RLC, "%s:%d:%s: fatal, module_id must be 0 for eNB\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (/*module_idP != 0 ||*/ eNB_index != 0 /*|| enb_flagP != 1 || MBMS_flagP != 0*/) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (enb_flagP) + T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(rntiP), + T_INT(channel_idP), T_INT(tb_sizeP)); + + /* TODO: better handle mbms, maybe we should not change rnti here */ + if (!enb_flagP && MBMS_flagP) { + rnti = 0xfffd; + /* TODO: handle channel_id properly */ + if (channel_idP != 5) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + channel_id = 7; + } else { + rnti = rntiP; + channel_id = channel_idP; + } + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rnti); + + switch (channel_id) { + case 1 ... 2: rb = ue->srb[channel_id - 1]; break; + case 3 ... 7: rb = ue->drb[channel_id - 3]; break; + default: rb = NULL; break; + } + + if (rb != NULL) { + rb->set_time(rb, rlc_current_time); + rb->recv_pdu(rb, buffer_pP, tb_sizeP); + } else { + LOG_E(RLC, "%s:%d:%s: fatal: no RB found (rnti %d channel ID %d)\n", + __FILE__, __LINE__, __FUNCTION__, rnti, channel_id); + exit(1); + } + + rlc_manager_unlock(rlc_ue_manager); +} + +tbs_size_t mac_rlc_data_req( + const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const eNB_flag_t enb_flagP, + const MBMS_flag_t MBMS_flagP, + const logical_chan_id_t channel_idP, + const tb_size_t tb_sizeP, + char *buffer_pP, + const uint32_t sourceL2Id, + const uint32_t destinationL2Id + ) +{ + int ret; + rlc_ue_t *ue; + rlc_entity_t *rb; + int maxsize; + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rntiP); + + switch (channel_idP) { + case 1 ... 2: rb = ue->srb[channel_idP - 1]; break; + case 3 ... 7: rb = ue->drb[channel_idP - 3]; break; + default: rb = NULL; break; + } + + if (MBMS_flagP == MBMS_FLAG_YES) { + if (channel_idP >= 1 && channel_idP <= 5) + rb = ue->drb[channel_idP - 1]; + else + rb = NULL; + } + + + if (rb != NULL) { + rb->set_time(rb, rlc_current_time); + maxsize = tb_sizeP; + ret = rb->generate_pdu(rb, buffer_pP, maxsize); + } else { + LOG_E(RLC, "%s:%d:%s: fatal: data req for unknown RB\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + ret = 0; + } + + rlc_manager_unlock(rlc_ue_manager); + + if (enb_flagP) + T(T_ENB_RLC_MAC_DL, T_INT(module_idP), T_INT(rntiP), + T_INT(channel_idP), T_INT(ret)); + + return ret; +} + +mac_rlc_status_resp_t mac_rlc_status_ind( + const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const sub_frame_t subframeP, + const eNB_flag_t enb_flagP, + const MBMS_flag_t MBMS_flagP, + const logical_chan_id_t channel_idP, + const uint32_t sourceL2Id, + const uint32_t destinationL2Id + ) +{ + rlc_ue_t *ue; + 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); + + switch (channel_idP) { + case 1 ... 2: rb = ue->srb[channel_idP - 1]; break; + case 3 ... 7: rb = ue->drb[channel_idP - 3]; break; + default: rb = NULL; break; + } + + if (MBMS_flagP == MBMS_FLAG_YES) { + if (channel_idP >= 1 && channel_idP <= 5) + rb = ue->drb[channel_idP - 1]; + else + rb = NULL; + } + + if (rb != NULL) { + rlc_entity_buffer_status_t buf_stat; + rb->set_time(rb, rlc_current_time); + /* 36.321 deals with BSR values up to 3000000 bytes, after what it + * reports '> 3000000' (table 6.1.3.1-2). Passing 4000000 is thus + * more than enough. + */ + buf_stat = rb->buffer_status(rb, 4000000); + ret.bytes_in_buffer = buf_stat.status_size + + buf_stat.retx_size + + buf_stat.tx_size; + } else { + ret.bytes_in_buffer = 0; + } + + rlc_manager_unlock(rlc_ue_manager); + + ret.pdus_in_buffer = 0; + /* TODO: creation time may be important (unit: frame, as it seems) */ + ret.head_sdu_creation_time = 0; + ret.head_sdu_remaining_size_to_send = 0; + ret.head_sdu_is_segmented = 0; + return ret; +} + +rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( + const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const sub_frame_t subframeP, + const eNB_flag_t enb_flagP, + const logical_chan_id_t channel_idP) +{ + rlc_ue_t *ue; + rlc_buffer_occupancy_t ret; + rlc_entity_t *rb; + + if (enb_flagP) { + LOG_E(RLC, "Tx mac_rlc_get_buffer_occupancy_ind function is not implemented for eNB LcId=%u\n", channel_idP); + 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); + + switch (channel_idP) { + case 1 ... 2: rb = ue->srb[channel_idP - 1]; break; + case 3 ... 7: rb = ue->drb[channel_idP - 3]; break; + default: rb = NULL; break; + } + + if (rb != NULL) { + rlc_entity_buffer_status_t buf_stat; + rb->set_time(rb, rlc_current_time); + /* 36.321 deals with BSR values up to 3000000 bytes, after what it + * reports '> 3000000' (table 6.1.3.1-2). Passing 4000000 is thus + * more than enough. + */ + buf_stat = rb->buffer_status(rb, 4000000); + ret = buf_stat.status_size + + buf_stat.retx_size + + buf_stat.tx_size; + } else { + ret = 0; + } + + rlc_manager_unlock(rlc_ue_manager); + + return ret; +} + +int oai_emulation; + +rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + confirm_t confirmP, + sdu_size_t sdu_sizeP, + mem_block_t *sdu_pP, + const uint32_t *const sourceL2Id, + const uint32_t *const destinationL2Id + ) +{ + int rnti = ctxt_pP->rnti; + rlc_ue_t *ue; + rlc_entity_t *rb; + + if (MBMS_flagP == MBMS_FLAG_YES) + rnti = 0xfffd; + + LOG_D(RLC, "%s rnti %d srb_flag %d rb_id %d mui %d confirm %d sdu_size %d MBMS_flag %d\n", + __FUNCTION__, rnti, srb_flagP, (int)rb_idP, muiP, confirmP, sdu_sizeP, + MBMS_flagP); + + if (ctxt_pP->enb_flag) + T(T_ENB_RLC_DL, T_INT(ctxt_pP->module_id), + T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_sizeP)); + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rnti); + + rb = NULL; + + if (srb_flagP) { + if (rb_idP >= 1 && rb_idP <= 2) + rb = ue->srb[rb_idP - 1]; + } else { + if (rb_idP >= 1 && rb_idP <= 5) + rb = ue->drb[rb_idP - 1]; + } + + if( MBMS_flagP == MBMS_FLAG_YES) { + if (rb_idP >= 1 && rb_idP <= 5) + rb = ue->drb[rb_idP - 1]; + } + + if (rb != NULL) { + rb->set_time(rb, rlc_current_time); + rb->recv_sdu(rb, (char *)sdu_pP->data, sdu_sizeP, muiP); + } else { + LOG_E(RLC, "%s:%d:%s: fatal: SDU sent to unknown RB\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + rlc_manager_unlock(rlc_ue_manager); + + free_mem_block(sdu_pP, __func__); + + return RLC_OP_STATUS_OK; +} + +int rlc_module_init(int enb_flag) +{ + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + static int inited = 0; + + if (pthread_mutex_lock(&lock)) abort(); + + if (inited) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + inited = 1; + + rlc_ue_manager = new_rlc_ue_manager(enb_flag); + + if (pthread_mutex_unlock(&lock)) abort(); + + return 0; +} + +void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP) +{ +} + +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + +static void deliver_sdu(void *_ue, rlc_entity_t *entity, char *buf, int size) +{ + rlc_ue_t *ue = _ue; + int is_srb; + int rb_id; + protocol_ctxt_t ctx; + mem_block_t *memblock; + int i; + int is_enb; + int is_mbms; + + /* TODO: be sure it's fine to check rnti for MBMS */ + is_mbms = ue->rnti == 0xfffd; + + /* is it SRB? */ + for (i = 0; i < 2; i++) { + if (entity == ue->srb[i]) { + is_srb = 1; + rb_id = i+1; + goto rb_found; + } + } + + /* maybe DRB? */ + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + is_srb = 0; + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +rb_found: + LOG_D(RLC, "%s:%d:%s: delivering SDU (rnti %d is_srb %d rb_id %d) size %d", + __FILE__, __LINE__, __FUNCTION__, ue->rnti, is_srb, rb_id, size); + + memblock = get_free_mem_block(size, __func__); + if (memblock == NULL) { + LOG_E(RLC, "%s:%d:%s: ERROR: get_free_mem_block failed\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + memcpy(memblock->data, buf, size); + + /* unused fields? */ + ctx.instance = ue->module_id; + ctx.frame = 0; + ctx.subframe = 0; + ctx.eNB_index = 0; + ctx.configured = 1; + ctx.brOption = 0; + + /* used fields? */ + ctx.module_id = ue->module_id; + ctx.rnti = ue->rnti; + + is_enb = rlc_manager_get_enb_flag(rlc_ue_manager); + ctx.enb_flag = is_enb; + + if (is_enb) { + T(T_ENB_RLC_UL, + T_INT(0 /*ctxt_pP->module_id*/), + T_INT(ue->rnti), T_INT(rb_id), T_INT(size)); + + const ngran_node_t type = RC.rrc[0 /*ctxt_pP->module_id*/]->node_type; + AssertFatal(type != ngran_eNB_CU && type != ngran_ng_eNB_CU && type != ngran_gNB_CU, + "Can't be CU, bad node type %d\n", type); + + if (NODE_IS_DU(type) && is_srb == 1) { + MessageDef *msg = itti_alloc_new_message(TASK_RLC_ENB, F1AP_UL_RRC_MESSAGE); + F1AP_UL_RRC_MESSAGE(msg).rnti = ue->rnti; + F1AP_UL_RRC_MESSAGE(msg).srb_id = rb_id; + F1AP_UL_RRC_MESSAGE(msg).rrc_container = (unsigned char *)buf; + F1AP_UL_RRC_MESSAGE(msg).rrc_container_length = size; + itti_send_msg_to_task(TASK_DU_F1, ENB_MODULE_ID_TO_INSTANCE(0 /*ctxt_pP->module_id*/), msg); + return; + } + } + + if (!get_pdcp_data_ind_func()(&ctx, is_srb, is_mbms, rb_id, size, memblock, NULL, NULL)) { + LOG_E(RLC, "%s:%d:%s: ERROR: pdcp_data_ind failed (is_srb %d rb_id %d rnti %d)\n", + __FILE__, __LINE__, __FUNCTION__, + is_srb, rb_id, ue->rnti); + /* what to do in case of failure? for the moment: nothing */ + } +} + +static void successful_delivery(void *_ue, rlc_entity_t *entity, int sdu_id) +{ + rlc_ue_t *ue = _ue; + int i; + int is_srb; + int rb_id; + MessageDef *msg; + int is_enb; + + /* is it SRB? */ + for (i = 0; i < 2; i++) { + if (entity == ue->srb[i]) { + is_srb = 1; + rb_id = i+1; + goto rb_found; + } + } + + /* maybe DRB? */ + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + is_srb = 0; + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +rb_found: + LOG_D(RLC, "sdu %d was successfully delivered on %s %d\n", + sdu_id, + is_srb ? "SRB" : "DRB", + rb_id); + + /* TODO: do something for DRBs? */ + if (is_srb == 0) + return; + + is_enb = rlc_manager_get_enb_flag(rlc_ue_manager); + if (!is_enb) + return; + + msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION); + RLC_SDU_INDICATION(msg).rnti = ue->rnti; + RLC_SDU_INDICATION(msg).is_successful = 1; + RLC_SDU_INDICATION(msg).srb_id = rb_id; + RLC_SDU_INDICATION(msg).message_id = sdu_id; + /* TODO: accept more than 1 instance? here we send to instance id 0 */ + itti_send_msg_to_task(TASK_RRC_ENB, 0, msg); +} + +static void max_retx_reached(void *_ue, rlc_entity_t *entity) +{ + rlc_ue_t *ue = _ue; + int i; + int is_srb; + int rb_id; + MessageDef *msg; + int is_enb; + + /* is it SRB? */ + for (i = 0; i < 2; i++) { + if (entity == ue->srb[i]) { + is_srb = 1; + rb_id = i+1; + goto rb_found; + } + } + + /* maybe DRB? */ + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + is_srb = 0; + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +rb_found: + LOG_D(RLC, "max RETX reached on %s %d\n", + is_srb ? "SRB" : "DRB", + rb_id); + + /* TODO: do something for DRBs? */ + if (is_srb == 0) + return; + + is_enb = rlc_manager_get_enb_flag(rlc_ue_manager); + if (!is_enb) + return; + + msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION); + RLC_SDU_INDICATION(msg).rnti = ue->rnti; + RLC_SDU_INDICATION(msg).is_successful = 0; + RLC_SDU_INDICATION(msg).srb_id = rb_id; + RLC_SDU_INDICATION(msg).message_id = -1; + /* TODO: accept more than 1 instance? here we send to instance id 0 */ + itti_send_msg_to_task(TASK_RRC_ENB, 0, msg); +} + +static void add_srb(int rnti, int module_id, struct LTE_SRB_ToAddMod *s) +{ + rlc_entity_t *rlc_am; + rlc_ue_t *ue; + + struct LTE_SRB_ToAddMod__rlc_Config *r = s->rlc_Config; + struct LTE_SRB_ToAddMod__logicalChannelConfig *l = s->logicalChannelConfig; + int srb_id = s->srb_Identity; + int logical_channel_group; + + int t_reordering; + int t_status_prohibit; + int t_poll_retransmit; + int poll_pdu; + int poll_byte; + int max_retx_threshold; + + if (srb_id != 1 && srb_id != 2) { + LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n", + __FILE__, __LINE__, __FUNCTION__, srb_id); + exit(1); + } + + switch (l->present) { + case LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue: + logical_channel_group = *l->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup; + break; + case LTE_SRB_ToAddMod__logicalChannelConfig_PR_defaultValue: + /* default value from 36.331 9.2.1 */ + logical_channel_group = 0; + break; + default: + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + /* TODO: accept other values? */ + if (logical_channel_group != 0) { + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + switch (r->present) { + case LTE_SRB_ToAddMod__rlc_Config_PR_explicitValue: { + struct LTE_RLC_Config__am *am; + if (r->choice.explicitValue.present != LTE_RLC_Config_PR_am) { + LOG_E(RLC, "%s:%d:%s: fatal error, must be RLC AM\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + am = &r->choice.explicitValue.choice.am; + t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); + t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); + t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); + poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); + poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte); + max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold); + break; + } + case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue: + /* default values from 36.331 9.2.1 */ + t_reordering = 35; + t_status_prohibit = 0; + t_poll_retransmit = 45; + poll_pdu = -1; + poll_byte = -1; + max_retx_threshold = 4; + break; + default: + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rnti); + ue->module_id = module_id; + 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); + } else { + rlc_am = new_rlc_entity_am(100000, + 100000, + deliver_sdu, ue, + successful_delivery, ue, + max_retx_reached, ue, + t_reordering, t_status_prohibit, + t_poll_retransmit, + 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); + } + rlc_manager_unlock(rlc_ue_manager); +} + +static void add_drb_am(int rnti, int module_id, struct LTE_DRB_ToAddMod *s) +{ + rlc_entity_t *rlc_am; + rlc_ue_t *ue; + + struct LTE_RLC_Config *r = s->rlc_Config; + struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + int drb_id = s->drb_Identity; + int channel_id = *s->logicalChannelIdentity; + int logical_channel_group; + + int t_reordering; + int t_status_prohibit; + int t_poll_retransmit; + int poll_pdu; + int poll_byte; + int max_retx_threshold; + + if (!(drb_id >= 1 && drb_id <= 5)) { + LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id); + exit(1); + } + + if (channel_id != drb_id + 2) { + LOG_E(RLC, "%s:%d:%s: todo, remove this limitation\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup; + + /* TODO: accept other values? */ + if (logical_channel_group != 1) { + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + switch (r->present) { + case LTE_RLC_Config_PR_am: { + struct LTE_RLC_Config__am *am; + am = &r->choice.am; + t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); + t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); + t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); + poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); + poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte); + max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold); + break; + } + default: + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rnti); + ue->module_id = module_id; + 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); + } else { + rlc_am = new_rlc_entity_am(1000000, + 1000000, + deliver_sdu, ue, + successful_delivery, ue, + max_retx_reached, ue, + t_reordering, t_status_prohibit, + t_poll_retransmit, + 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); + } + rlc_manager_unlock(rlc_ue_manager); +} + +static void add_drb_um(int rnti, int module_id, struct LTE_DRB_ToAddMod *s) +{ + rlc_entity_t *rlc_um; + rlc_ue_t *ue; + + struct LTE_RLC_Config *r = s->rlc_Config; + struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + int drb_id = s->drb_Identity; + int channel_id = *s->logicalChannelIdentity; + int logical_channel_group; + + int t_reordering; + int sn_field_length; + + if (!(drb_id >= 1 && drb_id <= 5)) { + LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id); + exit(1); + } + + if (channel_id != drb_id + 2) { + LOG_E(RLC, "%s:%d:%s: todo, remove this limitation\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup; + + /* TODO: accept other values? */ + if (logical_channel_group != 1) { + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + switch (r->present) { + case LTE_RLC_Config_PR_um_Bi_Directional: { + struct LTE_RLC_Config__um_Bi_Directional *um; + um = &r->choice.um_Bi_Directional; + t_reordering = decode_t_reordering(um->dl_UM_RLC.t_Reordering); + if (um->dl_UM_RLC.sn_FieldLength != um->ul_UM_RLC.sn_FieldLength) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + sn_field_length = decode_sn_field_length(um->dl_UM_RLC.sn_FieldLength); + break; + } + default: + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rnti); + ue->module_id = module_id; + 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); + } else { + rlc_um = new_rlc_entity_um(1000000, + 1000000, + deliver_sdu, ue, + t_reordering, + 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); + } + rlc_manager_unlock(rlc_ue_manager); +} + +static void add_drb(int rnti, int module_id, struct LTE_DRB_ToAddMod *s) +{ + switch (s->rlc_Config->present) { + case LTE_RLC_Config_PR_am: + add_drb_am(rnti, module_id, s); + break; + case LTE_RLC_Config_PR_um_Bi_Directional: + add_drb_um(rnti, module_id, s); + break; + default: + LOG_E(RLC, "%s:%d:%s: fatal: unhandled DRB type\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const LTE_SRB_ToAddModList_t * const srb2add_listP, + const LTE_DRB_ToAddModList_t * const drb2add_listP, + const LTE_DRB_ToReleaseList_t * const drb2release_listP, + const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, + const uint32_t sourceL2Id, + const uint32_t destinationL2Id + ) +{ + int rnti = ctxt_pP->rnti; + int module_id = ctxt_pP->module_id; + int i; + int j; + + if (ctxt_pP->enb_flag == 1 && + (ctxt_pP->module_id != 0 || ctxt_pP->instance != 0)) { + LOG_E(RLC, "%s: module_id != 0 or instance != 0 not handled for eNB\n", + __FUNCTION__); + exit(1); + } + + if (0 /*|| + ctxt_pP->instance != 0 || ctxt_pP->eNB_index != 0 || + ctxt_pP->configured != 1 || ctxt_pP->brOption != 0 */) { + LOG_E(RLC, "%s: ctxt_pP not handled (%d %d %d %d %d %d)\n", __FUNCTION__, + ctxt_pP->enb_flag , ctxt_pP->module_id, ctxt_pP->instance, + ctxt_pP->eNB_index, ctxt_pP->configured, ctxt_pP->brOption); + exit(1); + } + + if (pmch_InfoList_r9_pP != NULL) { + int mbms_rnti = 0xfffd; + LTE_MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL; + LTE_MBMS_SessionInfo_r9_t *MBMS_SessionInfo_p = NULL; + mbms_session_id_t mbms_session_id; + mbms_service_id_t mbms_service_id; + rb_id_t drb_id = 0; + logical_chan_id_t lc_id = 0; + //LTE_DRB_Identity_t drb_id = 0; + //LTE_DRB_Identity_t* pdrb_id = NULL; + + for (i=0; ilist.count; i++) { + mbms_SessionInfoList_r9_p = &(pmch_InfoList_r9_pP->list.array[i]->mbms_SessionInfoList_r9); + + for (j=0; jlist.count; j++) { + MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j]; + if (0/*MBMS_SessionInfo_p->sessionId_r9*/) + mbms_session_id = MBMS_SessionInfo_p->sessionId_r9->buf[0]; + else + mbms_session_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9; + lc_id = mbms_session_id; + mbms_service_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string +// mbms_service_id = j; + +#if 0 + /* TODO: check if this code should stay there + * as it is both enb and ue cases do the same thing + */ + // can set the mch_id = i + if (ctxt_pP->enb_flag) { + drb_id = (mbms_service_id * LTE_maxSessionPerPMCH ) + mbms_session_id;//+ (LTE_maxDRB + 3) * MAX_MOBILES_PER_ENB; // 1 + } else { + drb_id = (mbms_service_id * LTE_maxSessionPerPMCH ) + mbms_session_id; // + (LTE_maxDRB + 3); // 15 + } +#endif + + drb_id = (mbms_service_id * LTE_maxSessionPerPMCH ) + mbms_session_id; + + LOG_I(RLC, PROTOCOL_CTXT_FMT" CONFIG REQ MBMS ASN1 LC ID %u RB ID %u SESSION ID %u SERVICE ID %u, mbms_rnti %x\n", + PROTOCOL_CTXT_ARGS(ctxt_pP), + lc_id, + (int)drb_id, + mbms_session_id, + mbms_service_id, + mbms_rnti + ); + + rlc_entity_t *rlc_um; + rlc_ue_t *ue; + + //drb_id = rb_id; + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, mbms_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__, (int)drb_id, mbms_rnti); + } else { + rlc_um = new_rlc_entity_um(1000000, + 1000000, + deliver_sdu, ue, + 0,//LTE_T_Reordering_ms0,//t_reordering, + 5//LTE_SN_FieldLength_size5//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__, (int)drb_id, mbms_rnti); + } + rlc_manager_unlock(rlc_ue_manager); + + } + } + + } + + if (drb2release_listP != NULL) { + LOG_E(RLC, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (srb2add_listP != NULL) { + for (i = 0; i < srb2add_listP->list.count; i++) { + add_srb(rnti, module_id, srb2add_listP->list.array[i]); + } + } + + if (drb2add_listP != NULL) { + for (i = 0; i < drb2add_listP->list.count; i++) { + add_drb(rnti, module_id, drb2add_listP->list.array[i]); + } + } + + return RLC_OP_STATUS_OK; +} + +rlc_op_status_t rrc_rlc_config_req ( + const protocol_ctxt_t* const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t mbms_flagP, + const config_action_t actionP, + const rb_id_t rb_idP, + const rlc_info_t rlc_infoP) +{ + rlc_ue_t *ue; + int i; + + if (mbms_flagP) { + LOG_E(RLC, "%s:%d:%s: todo (mbms not supported)\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + if (actionP != CONFIG_ACTION_REMOVE) { + LOG_E(RLC, "%s:%d:%s: todo (only CONFIG_ACTION_REMOVE supported)\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + if (ctxt_pP->module_id) { + LOG_E(RLC, "%s:%d:%s: todo (only module_id 0 supported)\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + if ((srb_flagP && !(rb_idP >= 1 && rb_idP <= 2)) || + (!srb_flagP && !(rb_idP >= 1 && rb_idP <= 5))) { + LOG_E(RLC, "%s:%d:%s: bad rb_id (%d) (is_srb %d)\n", __FILE__, __LINE__, __FUNCTION__, (int)rb_idP, srb_flagP); + exit(1); + } + rlc_manager_lock(rlc_ue_manager); + LOG_D(RLC, "%s:%d:%s: remove rb %d (is_srb %d) for UE %d\n", __FILE__, __LINE__, __FUNCTION__, (int)rb_idP, srb_flagP, ctxt_pP->rnti); + ue = rlc_manager_get_ue(rlc_ue_manager, ctxt_pP->rnti); + if (srb_flagP) { + if (ue->srb[rb_idP-1] != NULL) { + ue->srb[rb_idP-1]->delete(ue->srb[rb_idP-1]); + ue->srb[rb_idP-1] = NULL; + } else + LOG_W(RLC, "removing non allocated SRB %d, do nothing\n", (int)rb_idP); + } else { + if (ue->drb[rb_idP-1] != NULL) { + ue->drb[rb_idP-1]->delete(ue->drb[rb_idP-1]); + ue->drb[rb_idP-1] = NULL; + } else + LOG_W(RLC, "removing non allocated DRB %d, do nothing\n", (int)rb_idP); + } + /* remove UE if it has no more RB configured */ + for (i = 0; i < 2; i++) + if (ue->srb[i] != NULL) + break; + if (i == 2) { + for (i = 0; i < 5; i++) + if (ue->drb[i] != NULL) + break; + if (i == 5) + rlc_manager_remove_ue(rlc_ue_manager, ctxt_pP->rnti); + } + rlc_manager_unlock(rlc_ue_manager); + return RLC_OP_STATUS_OK; +} + +void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t rrc_data_confP) +{ + /* nothing to do */ +} + +rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) +{ + LOG_D(RLC, "%s:%d:%s: remove UE %d\n", __FILE__, __LINE__, __FUNCTION__, x->rnti); + rlc_manager_lock(rlc_ue_manager); + rlc_manager_remove_ue(rlc_ue_manager, x->rnti); + rlc_manager_unlock(rlc_ue_manager); + + return RLC_OP_STATUS_OK; +} diff --git a/openair2/LAYER2/rlc_v2/rlc_pdu.c b/openair2/LAYER2/rlc_v2/rlc_pdu.c new file mode 100644 index 0000000000..c55e2d9c3c --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_pdu.c @@ -0,0 +1,266 @@ +/* + * 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 "rlc_pdu.h" + +#include +#include + +#include "LOG/log.h" + +/**************************************************************************/ +/* RX PDU segment and segment list */ +/**************************************************************************/ + +rlc_rx_pdu_segment_t *rlc_rx_new_pdu_segment(int sn, int so, int size, + int is_last, char *data, int data_offset) +{ + rlc_rx_pdu_segment_t *ret = malloc(sizeof(rlc_rx_pdu_segment_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + ret->sn = sn; + ret->so = so; + ret->size = size; + ret->is_last = is_last; + ret->next = NULL; + + ret->data = malloc(size); + if (ret->data == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + memcpy(ret->data, data, size); + + ret->data_offset = data_offset; + + return ret; +} + +void rlc_rx_free_pdu_segment(rlc_rx_pdu_segment_t *pdu_segment) +{ + free(pdu_segment->data); + free(pdu_segment); +} + +rlc_rx_pdu_segment_t *rlc_rx_pdu_segment_list_add( + int (*sn_compare)(void *, int, int), void *sn_compare_data, + rlc_rx_pdu_segment_t *list, rlc_rx_pdu_segment_t *pdu_segment) +{ + rlc_rx_pdu_segment_t head; + rlc_rx_pdu_segment_t *cur; + rlc_rx_pdu_segment_t *prev; + + head.next = list; + cur = list; + prev = &head; + + /* order is by 'sn', if 'sn' is the same then order is by 'so' */ + while (cur != NULL) { + /* check if 'pdu_segment' is before 'cur' in the list */ + if (sn_compare(sn_compare_data, cur->sn, pdu_segment->sn) > 0 || + (cur->sn == pdu_segment->sn && cur->so > pdu_segment->so)) { + break; + } + prev = cur; + cur = cur->next; + } + prev->next = pdu_segment; + pdu_segment->next = cur; + return head.next; +} + +/**************************************************************************/ +/* TX PDU management */ +/**************************************************************************/ + +rlc_tx_pdu_segment_t *rlc_tx_new_pdu(void) +{ + rlc_tx_pdu_segment_t *ret = calloc(1, sizeof(rlc_tx_pdu_segment_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + ret->retx_count = -1; + return ret; +} + +void rlc_tx_free_pdu(rlc_tx_pdu_segment_t *pdu) +{ + free(pdu); +} + +rlc_tx_pdu_segment_t *rlc_tx_pdu_list_append(rlc_tx_pdu_segment_t *list, + rlc_tx_pdu_segment_t *pdu) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + + head.next = list; + + cur = &head; + while (cur->next != NULL) { + cur = cur->next; + } + cur->next = pdu; + + return head.next; +} + +rlc_tx_pdu_segment_t *rlc_tx_pdu_list_add( + int (*sn_compare)(void *, int, int), void *sn_compare_data, + rlc_tx_pdu_segment_t *list, rlc_tx_pdu_segment_t *pdu_segment) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + + head.next = list; + cur = list; + prev = &head; + + /* order is by 'sn', if 'sn' is the same then order is by 'so' */ + while (cur != NULL) { + /* check if 'pdu_segment' is before 'cur' in the list */ + if (sn_compare(sn_compare_data, cur->sn, pdu_segment->sn) > 0 || + (cur->sn == pdu_segment->sn && cur->so > pdu_segment->so)) { + break; + } + prev = cur; + cur = cur->next; + } + prev->next = pdu_segment; + pdu_segment->next = cur; + return head.next; +} + +/**************************************************************************/ +/* PDU decoder */ +/**************************************************************************/ + +void rlc_pdu_decoder_init(rlc_pdu_decoder_t *decoder, char *buffer, int size) +{ + decoder->error = 0; + decoder->byte = 0; + decoder->bit = 0; + decoder->buffer = buffer; + decoder->size = size; +} + +static int get_bit(rlc_pdu_decoder_t *decoder) +{ + int ret; + + if (decoder->byte >= decoder->size) { + decoder->error = 1; + return 0; + } + + ret = (decoder->buffer[decoder->byte] >> (7 - decoder->bit)) & 1; + + decoder->bit++; + if (decoder->bit == 8) { + decoder->bit = 0; + decoder->byte++; + } + + return ret; +} + +int rlc_pdu_decoder_get_bits(rlc_pdu_decoder_t *decoder, int count) +{ + int ret = 0; + int i; + + if (count > 31) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + for (i = 0; i < count; i++) { + ret <<= 1; + ret |= get_bit(decoder); + if (decoder->error) return -1; + } + + return ret; +} + +void rlc_pdu_decoder_align(rlc_pdu_decoder_t *decoder) +{ + if (decoder->bit) { + decoder->bit = 0; + decoder->byte++; + } +} + +/**************************************************************************/ +/* PDU encoder */ +/**************************************************************************/ + +void rlc_pdu_encoder_init(rlc_pdu_encoder_t *encoder, char *buffer, int size) +{ + encoder->byte = 0; + encoder->bit = 0; + encoder->buffer = buffer; + encoder->size = size; +} + +static void put_bit(rlc_pdu_encoder_t *encoder, int bit) +{ + if (encoder->byte == encoder->size) { + LOG_E(RLC, "%s:%d:%s: fatal, buffer full\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + encoder->buffer[encoder->byte] <<= 1; + if (bit) + encoder->buffer[encoder->byte] |= 1; + + encoder->bit++; + if (encoder->bit == 8) { + encoder->bit = 0; + encoder->byte++; + } +} + +void rlc_pdu_encoder_put_bits(rlc_pdu_encoder_t *encoder, int value, int count) +{ + int i; + int x; + + if (count > 31) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + x = 1 << (count - 1); + for (i = 0; i < count; i++, x >>= 1) + put_bit(encoder, value & x); +} + +void rlc_pdu_encoder_align(rlc_pdu_encoder_t *encoder) +{ + while (encoder->bit) + put_bit(encoder, 0); +} diff --git a/openair2/LAYER2/rlc_v2/rlc_pdu.h b/openair2/LAYER2/rlc_v2/rlc_pdu.h new file mode 100644 index 0000000000..dbffe9f3cb --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_pdu.h @@ -0,0 +1,109 @@ +/* + * 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 _RLC_PDU_H_ +#define _RLC_PDU_H_ + +/**************************************************************************/ +/* RX PDU segment and segment list */ +/**************************************************************************/ + +typedef struct rlc_rx_pdu_segment_t { + int sn; + int so; + int size; + int is_last; + char *data; + int data_offset; + struct rlc_rx_pdu_segment_t *next; +} rlc_rx_pdu_segment_t; + +rlc_rx_pdu_segment_t *rlc_rx_new_pdu_segment(int sn, int so, int size, + int is_last, char *data, int data_offset); + +void rlc_rx_free_pdu_segment(rlc_rx_pdu_segment_t *pdu_segment); + +rlc_rx_pdu_segment_t *rlc_rx_pdu_segment_list_add( + int (*sn_compare)(void *, int, int), void *sn_compare_data, + rlc_rx_pdu_segment_t *list, rlc_rx_pdu_segment_t *pdu_segment); + +/**************************************************************************/ +/* TX PDU management */ +/**************************************************************************/ + +typedef struct rlc_tx_pdu_segment_t { + int sn; + void *start_sdu; /* real type is rlc_sdu_t * */ + int sdu_start_byte; /* starting byte in 'start_sdu' */ + int so; /* starting byte of the segment in full PDU */ + int data_size; /* number of data bytes (exclude header) */ + int is_segment; + int is_last; + int retx_count; + struct rlc_tx_pdu_segment_t *next; +} rlc_tx_pdu_segment_t; + +rlc_tx_pdu_segment_t *rlc_tx_new_pdu(void); +void rlc_tx_free_pdu(rlc_tx_pdu_segment_t *pdu); +rlc_tx_pdu_segment_t *rlc_tx_pdu_list_append(rlc_tx_pdu_segment_t *list, + rlc_tx_pdu_segment_t *pdu); +rlc_tx_pdu_segment_t *rlc_tx_pdu_list_add( + int (*sn_compare)(void *, int, int), void *sn_compare_data, + rlc_tx_pdu_segment_t *list, rlc_tx_pdu_segment_t *pdu_segment); + +/**************************************************************************/ +/* PDU decoder */ +/**************************************************************************/ + +typedef struct { + int error; + int byte; /* next byte to decode */ + int bit; /* next bit in next byte to decode */ + char *buffer; + int size; +} rlc_pdu_decoder_t; + +void rlc_pdu_decoder_init(rlc_pdu_decoder_t *decoder, char *buffer, int size); + +#define rlc_pdu_decoder_in_error(d) ((d)->error == 1) + +int rlc_pdu_decoder_get_bits(rlc_pdu_decoder_t *decoder, int count); + +void rlc_pdu_decoder_align(rlc_pdu_decoder_t *decoder); + +/**************************************************************************/ +/* PDU encoder */ +/**************************************************************************/ + +typedef struct { + int byte; /* next byte to encode */ + int bit; /* next bit in next byte to encode */ + char *buffer; + int size; +} rlc_pdu_encoder_t; + +void rlc_pdu_encoder_init(rlc_pdu_encoder_t *encoder, char *buffer, int size); + +void rlc_pdu_encoder_put_bits(rlc_pdu_encoder_t *encoder, int value, int count); + +void rlc_pdu_encoder_align(rlc_pdu_encoder_t *encoder); + +#endif /* _RLC_PDU_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_sdu.c b/openair2/LAYER2/rlc_v2/rlc_sdu.c new file mode 100644 index 0000000000..16465a9ff1 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_sdu.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 "rlc_sdu.h" + +#include +#include + +#include "LOG/log.h" + +rlc_sdu_t *rlc_new_sdu(char *buffer, int size, int upper_layer_id) +{ + rlc_sdu_t *ret = calloc(1, sizeof(rlc_sdu_t)); + if (ret == NULL) + goto oom; + + ret->upper_layer_id = upper_layer_id; + + ret->data = malloc(size); + if (ret->data == NULL) + goto oom; + + memcpy(ret->data, buffer, size); + + ret->size = size; + + return ret; + +oom: + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); +} + +void rlc_free_sdu(rlc_sdu_t *sdu) +{ + free(sdu->data); + free(sdu); +} + +void rlc_sdu_list_add(rlc_sdu_t **list, rlc_sdu_t **end, rlc_sdu_t *sdu) +{ + if (*list == NULL) { + *list = sdu; + *end = sdu; + return; + } + + (*end)->next = sdu; + *end = sdu; +} diff --git a/openair2/UTIL/MEM/mem_pool.h b/openair2/LAYER2/rlc_v2/rlc_sdu.h similarity index 69% rename from openair2/UTIL/MEM/mem_pool.h rename to openair2/LAYER2/rlc_v2/rlc_sdu.h index cc0face78c..2c678956ee 100644 --- a/openair2/UTIL/MEM/mem_pool.h +++ b/openair2/LAYER2/rlc_v2/rlc_sdu.h @@ -19,20 +19,21 @@ * contact@openairinterface.org */ -/*************************************************************************** - mem_pool.h - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr +#ifndef _RLC_SDU_H_ +#define _RLC_SDU_H_ +typedef struct rlc_sdu_t { + int upper_layer_id; + char *data; + int size; + /* next_byte indicates the starting byte to use to construct a new PDU */ + int next_byte; + int acked_bytes; + struct rlc_sdu_t *next; +} rlc_sdu_t; - ***************************************************************************/ -#ifndef __MEM_POOL_H__ -# define __MEM_POOL_H__ +rlc_sdu_t *rlc_new_sdu(char *buffer, int size, int upper_layer_id); +void rlc_free_sdu(rlc_sdu_t *sdu); +void rlc_sdu_list_add(rlc_sdu_t **list, rlc_sdu_t **end, rlc_sdu_t *sdu); -# include "list.h" -# include "mem_block.h" - - -#endif +#endif /* _RLC_SDU_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_ue_manager.c b/openair2/LAYER2/rlc_v2/rlc_ue_manager.c new file mode 100644 index 0000000000..1fd366fda1 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_ue_manager.c @@ -0,0 +1,190 @@ +/* + * 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 "rlc_ue_manager.h" + +#include +#include +#include + +#include "LOG/log.h" + +typedef struct { + pthread_mutex_t lock; + rlc_ue_t **ue_list; + int ue_count; + int enb_flag; +} rlc_ue_manager_internal_t; + +rlc_ue_manager_t *new_rlc_ue_manager(int enb_flag) +{ + rlc_ue_manager_internal_t *ret; + + ret = calloc(1, sizeof(rlc_ue_manager_internal_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (pthread_mutex_init(&ret->lock, NULL)) abort(); + ret->enb_flag = enb_flag; + + return ret; +} + +int rlc_manager_get_enb_flag(rlc_ue_manager_t *_m) +{ + rlc_ue_manager_internal_t *m = _m; + return m->enb_flag; +} + +void rlc_manager_lock(rlc_ue_manager_t *_m) +{ + rlc_ue_manager_internal_t *m = _m; + if (pthread_mutex_lock(&m->lock)) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +void rlc_manager_unlock(rlc_ue_manager_t *_m) +{ + rlc_ue_manager_internal_t *m = _m; + if (pthread_mutex_unlock(&m->lock)) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +rlc_ue_t *rlc_manager_get_ue(rlc_ue_manager_t *_m, int rnti) +{ + /* TODO: optimze */ + rlc_ue_manager_internal_t *m = _m; + int i; + + for (i = 0; i < m->ue_count; i++) + 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); + + m->ue_count++; + m->ue_list = realloc(m->ue_list, sizeof(rlc_ue_t *) * m->ue_count); + if (m->ue_list == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + m->ue_list[m->ue_count-1] = calloc(1, sizeof(rlc_ue_t)); + if (m->ue_list[m->ue_count-1] == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + m->ue_list[m->ue_count-1]->rnti = rnti; + + return m->ue_list[m->ue_count-1]; +} + +/* must be called with lock acquired */ +void rlc_manager_remove_ue(rlc_ue_manager_t *_m, int rnti) +{ + rlc_ue_manager_internal_t *m = _m; + rlc_ue_t *ue; + int i; + int j; + + for (i = 0; i < m->ue_count; i++) + if (m->ue_list[i]->rnti == rnti) + break; + + if (i == m->ue_count) { + LOG_D(RLC, "%s:%d:%s: warning: ue %d not found\n", + __FILE__, __LINE__, __FUNCTION__, + rnti); + return; + } + + ue = m->ue_list[i]; + + for (j = 0; j < 2; j++) + if (ue->srb[j] != NULL) + ue->srb[j]->delete(ue->srb[j]); + + for (j = 0; j < 5; j++) + if (ue->drb[j] != NULL) + ue->drb[j]->delete(ue->drb[j]); + + free(ue); + + m->ue_count--; + if (m->ue_count == 0) { + free(m->ue_list); + m->ue_list = NULL; + return; + } + + memmove(&m->ue_list[i], &m->ue_list[i+1], + (m->ue_count - i) * sizeof(rlc_ue_t *)); + m->ue_list = realloc(m->ue_list, m->ue_count * sizeof(rlc_ue_t *)); + if (m->ue_list == NULL) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +void rlc_ue_add_srb_rlc_entity(rlc_ue_t *ue, int srb_id, rlc_entity_t *entity) +{ + if (srb_id < 1 || srb_id > 2) { + LOG_E(RLC, "%s:%d:%s: fatal, bad srb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + srb_id--; + + if (ue->srb[srb_id] != NULL) { + LOG_E(RLC, "%s:%d:%s: fatal, srb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->srb[srb_id] = entity; +} + +/* must be called with lock acquired */ +void rlc_ue_add_drb_rlc_entity(rlc_ue_t *ue, int drb_id, rlc_entity_t *entity) +{ + if (drb_id < 1 || drb_id > 5) { + LOG_E(RLC, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + drb_id--; + + if (ue->drb[drb_id] != NULL) { + LOG_E(RLC, "%s:%d:%s: fatal, drb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->drb[drb_id] = entity; +} diff --git a/openair2/LAYER2/rlc_v2/rlc_ue_manager.h b/openair2/LAYER2/rlc_v2/rlc_ue_manager.h new file mode 100644 index 0000000000..81bb0d0fa1 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_ue_manager.h @@ -0,0 +1,57 @@ +/* + * 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 _RLC_UE_MANAGER_H_ +#define _RLC_UE_MANAGER_H_ + +#include "rlc_entity.h" + +typedef void rlc_ue_manager_t; + +typedef struct rlc_ue_t { + int rnti; + int module_id; /* necesarry for the L2 simulator - not clean, to revise */ + rlc_entity_t *srb[2]; + rlc_entity_t *drb[5]; +} rlc_ue_t; + +/***********************************************************************/ +/* manager functions */ +/***********************************************************************/ + +rlc_ue_manager_t *new_rlc_ue_manager(int enb_flag); + +int rlc_manager_get_enb_flag(rlc_ue_manager_t *m); + +void rlc_manager_lock(rlc_ue_manager_t *m); +void rlc_manager_unlock(rlc_ue_manager_t *m); + +rlc_ue_t *rlc_manager_get_ue(rlc_ue_manager_t *m, int rnti); +void rlc_manager_remove_ue(rlc_ue_manager_t *m, int rnti); + +/***********************************************************************/ +/* ue functions */ +/***********************************************************************/ + +void rlc_ue_add_srb_rlc_entity(rlc_ue_t *ue, int srb_id, rlc_entity_t *entity); +void rlc_ue_add_drb_rlc_entity(rlc_ue_t *ue, int drb_id, rlc_entity_t *entity); + +#endif /* _RLC_UE_MANAGER_H_ */ diff --git a/openair2/LAYER2/rlc_v2/tests/LOG/log.h b/openair2/LAYER2/rlc_v2/tests/LOG/log.h new file mode 100644 index 0000000000..5c9fcd643c --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/LOG/log.h @@ -0,0 +1,10 @@ +#ifndef _LOG_H_ +#define _LOG_H_ + +#include + +#define LOG_E(x, ...) printf(__VA_ARGS__) +#define LOG_D(x, ...) printf(__VA_ARGS__) +#define LOG_W(x, ...) printf(__VA_ARGS__) + +#endif /* _LOG_H_ */ diff --git a/openair2/LAYER2/rlc_v2/tests/Makefile b/openair2/LAYER2/rlc_v2/tests/Makefile new file mode 100644 index 0000000000..14bb186d4c --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/Makefile @@ -0,0 +1,32 @@ +CC=gcc +CFLAGS=-Wall -g --coverage -I. + +LIB=rlc_entity.o rlc_entity_am.o rlc_entity_um.o rlc_pdu.o rlc_sdu.o + +tests: + @./run_tests.sh + +all: clean_run $(TEST).run + +%.run: $(TEST).bin + #valgrind ./$(TEST).bin > $(TEST).run_pre 2> $(TEST).valgrind + ./$(TEST).bin > $(TEST).run_pre + grep ^TEST $(TEST).run_pre > $(TEST).run + gunzip -c $(TEST).txt.gz > $(TEST).txt + diff -q $(TEST).txt $(TEST).run + +$(TEST).bin: $(TEST).o $(LIB) + $(CC) $(CFLAGS) -o $@ $^ + +%.o: ../%.c + $(CC) $(CFLAGS) -I.. -c -o $@ $< + +$(TEST).o: test.c + $(CC) $(CFLAGS) -c -o $@ $< -DTEST='"$(TEST).h"' + +clean_run: + rm -f $(TEST).run $(TEST).bin $(TEST).o + +clean: + rm -f *.o *.bin *.run *.run_pre *.gcov *.gcda *.gcno test*.txt a.out \ + *.valgrind diff --git a/openair2/LAYER2/rlc_v2/tests/README b/openair2/LAYER2/rlc_v2/tests/README new file mode 100644 index 0000000000..db69cd4fa7 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/README @@ -0,0 +1,38 @@ +To run tests, simply type: make + +Each test is made of: + testXX.h definition of the test + testXX.txt.gz compressed expected output of the test + +At runtime, we generate: + testXX.run actual output of the test + +test.c is the test driving program. + +Only the output lines of the test program starting with "TEST" are +stored into testXX.txt and testXX.run. + +A test is considered a success if testXX.txt and testXX.run are equal. + +Only failed tests are reported. + +How to define a new test? + +1 - get the ID + + Look in the file run_tests.sh, the variable test_count gives you + the number of existing tests. The ID of your test has to be + test_count + 1. + +2 - create files + + Create the file test.h containing the test, then generate test.run + by running 'make all TEST=test' and copy test.run to test.txt. + Then compress this file (gzip -9 test.txt). Be sure that the output + is correct, of course. + + For the file names, replace by the actual number of the test. + For example, if your test ID is 47, then name the files test47.h and + test47.txt. And run 'make all TEST=test47' to generate test47.run. + +The available instructions for a test are described at the top of test.c. diff --git a/openair2/LAYER2/rlc_v2/tests/make_pdu.c b/openair2/LAYER2/rlc_v2/tests/make_pdu.c new file mode 100644 index 0000000000..057cc3e36d --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/make_pdu.c @@ -0,0 +1,29 @@ +/* gcc -Wall make_pdu.c -I.. ../rlc_pdu.c */ + +#include "rlc_pdu.h" +#include + +int main(void) +{ + char out[100]; + rlc_pdu_encoder_t e; + int i; + + rlc_pdu_encoder_init(&e, out, 100); + + rlc_pdu_encoder_put_bits(&e, 0, 1); // D/C + rlc_pdu_encoder_put_bits(&e, 0, 3); // CPT + rlc_pdu_encoder_put_bits(&e, 0, 10); // ack_sn + rlc_pdu_encoder_put_bits(&e, 1, 1); // e1 + rlc_pdu_encoder_put_bits(&e, 10, 10); // nack_sn + rlc_pdu_encoder_put_bits(&e, 0, 1); // e1 + rlc_pdu_encoder_put_bits(&e, 0, 1); // e2 + + rlc_pdu_encoder_align(&e); + + for (i = 0; i < e.byte; i++) printf(" %2.2x", (unsigned char)e.buffer[i]); + + printf("\n"); + + return 0; +} diff --git a/openair2/LAYER2/rlc_v2/tests/run_tests.sh b/openair2/LAYER2/rlc_v2/tests/run_tests.sh new file mode 100755 index 0000000000..72feff0036 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/run_tests.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +test_count=45 + +for i in `seq $test_count` +do + make all TEST=test$i >/dev/null 2>/dev/null + if [ $? != 0 ] + then + echo TEST $i FAILURE + fi +done diff --git a/openair2/LAYER2/rlc_v2/tests/test.c b/openair2/LAYER2/rlc_v2/tests/test.c new file mode 100644 index 0000000000..734e85f1f5 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/test.c @@ -0,0 +1,433 @@ +#include "../rlc_entity.h" +#include "../rlc_entity_am.h" +#include "../rlc_entity_um.h" + +#include +#include +#include +#include +#include +#include + +/* + * ENB_AM + * + * create the eNB RLC AM entity with given parameters + * + * UE_AM + * + * create the UE RLC AM entity with given parameters + * + * ENB_UM + * create the eNB RLC UM entity with given parameters + * + * UE_UM + * create the UE RLC UM entity with given parameters + * + * TIME