diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index 8dfa5c4ec4..c3b997a4e8 100644 --- a/ci-scripts/Jenkinsfile-gitlab +++ b/ci-scripts/Jenkinsfile-gitlab @@ -66,7 +66,8 @@ pipeline { "Test-IF4p5-TDD-Band38-Multi-RRU", "Test-eNB-OAI-UE-FDD-Band7", "Test-Mono-FDD-Band13-X2-HO", - "Test-TDD-Band78-gNB-NR-UE" + "Test-TDD-Band78-gNB-NR-UE", + "Test-OCP-FDD-Band7" ]) ansiColor('xterm') } @@ -683,6 +684,25 @@ pipeline { } } } + stage ("Test OAI OCP-eNB - FDD - Band 7 - B210") { + steps { + script { + triggerSlaveJob ('OCPeNB-FDD-Band7-B210', 'Test-OCP-FDD-Band7') + } + } + post { + always { + script { + finalizeSlaveJob('OCPeNB-FDD-Band7-B210') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } } post { always { diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py new file mode 100644 index 0000000000..1249f52172 --- /dev/null +++ b/ci-scripts/args_parse.py @@ -0,0 +1,229 @@ + +# * 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 Libs +#----------------------------------------------------------- +import sys # arg +import re # reg +import yaml + + +#----------------------------------------------------------- +# Parsing Command Line Arguements +#----------------------------------------------------------- + + +def ArgsParse(argvs,CiTestObj,RAN,HTML,EPC,ldpc,HELP): + + + py_param_file_present = False + py_params={} + + while len(argvs) > 1: + myArgv = argvs.pop(1) # 0th is this file's name + + #--help + if re.match('^\-\-help$', myArgv, re.IGNORECASE): + HELP.GenericHelp(CONST.Version) + sys.exit(0) + + #--apply= as parameters file, to replace inline parameters + elif re.match('^\-\-Apply=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-Apply=(.+)$', myArgv, re.IGNORECASE) + py_params_file = matchReg.group(1) + with open(py_params_file,'r') as file: + # The FullLoader parameter handles the conversion from YAML + # scalar values to Python dictionary format + py_params = yaml.load(file,Loader=yaml.FullLoader) + py_param_file_present = True #to be removed once validated + #AssignParams(py_params) #to be uncommented once validated + + #consider inline parameters + elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) + mode = matchReg.group(1) + elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ranRepository = matchReg.group(1) + RAN.ranRepository=matchReg.group(1) + HTML.ranRepository=matchReg.group(1) + ldpc.ranRepository=matchReg.group(1) + elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) + doMerge = matchReg.group(1) + ldpc.ranAllowMerge=matchReg.group(1) + if ((doMerge == 'true') or (doMerge == 'True')): + CiTestObj.ranAllowMerge = True + RAN.ranAllowMerge=True + HTML.ranAllowMerge=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) + CiTestObj.ranBranch = matchReg.group(1) + RAN.ranBranch=matchReg.group(1) + HTML.ranBranch=matchReg.group(1) + ldpc.ranBranch=matchReg.group(1) + elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) + CiTestObj.ranCommitID = matchReg.group(1) + RAN.ranCommitID=matchReg.group(1) + HTML.ranCommitID=matchReg.group(1) + ldpc.ranCommitID=matchReg.group(1) + elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) + CiTestObj.ranTargetBranch = matchReg.group(1) + RAN.ranTargetBranch=matchReg.group(1) + HTML.ranTargetBranch=matchReg.group(1) + ldpc.ranTargetBranch=matchReg.group(1) + elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) + RAN.eNBIPAddress=matchReg.group(1) + ldpc.eNBIpAddr=matchReg.group(1) + elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB1IPAddress=matchReg.group(1) + elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB2IPAddress=matchReg.group(1) + elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) + RAN.eNBUserName=matchReg.group(1) + ldpc.eNBUserName=matchReg.group(1) + elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB1UserName=matchReg.group(1) + elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB2UserName=matchReg.group(1) + elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) + RAN.eNBPassword=matchReg.group(1) + ldpc.eNBPassWord=matchReg.group(1) + elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB1Password=matchReg.group(1) + elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB2Password=matchReg.group(1) + elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + RAN.eNBSourceCodePath=matchReg.group(1) + ldpc.eNBSourceCodePath=matchReg.group(1) + elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB1SourceCodePath=matchReg.group(1) + elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + RAN.eNB2SourceCodePath=matchReg.group(1) + elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) + EPC.IPAddress=matchReg.group(1) + elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) + EPC.UserName=matchReg.group(1) + elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) + EPC.Password=matchReg.group(1) + elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + EPC.SourceCodePath=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) or re.match('OAI-Rel14-Docker', matchReg.group(1), re.IGNORECASE): + EPC.Type=matchReg.group(1) + else: + sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS or OAI-Rel14-Docker)') + elif re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE) + EPC.ContainerPrefix=matchReg.group(1) + elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ADBIPAddress = matchReg.group(1) + elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) + 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): + CiTestObj.ADBCentralized = False + else: + 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) + CiTestObj.ADBPassword = matchReg.group(1) + elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.testXMLfiles.append(matchReg.group(1)) + HTML.testXMLfiles.append(matchReg.group(1)) + HTML.nbTestXMLfiles=HTML.nbTestXMLfiles+1 + elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UEIPAddress = matchReg.group(1) + elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UEUserName = matchReg.group(1) + elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UEPassword = matchReg.group(1) + elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) + 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')): + CiTestObj.finalStatus = True + else: + HELP.GenericHelp(CONST.Version) + sys.exit('Invalid Parameter: ' + myArgv) + + return py_param_file_present, py_params, mode diff --git a/ci-scripts/cls_cots_ue.py b/ci-scripts/cls_cots_ue.py new file mode 100644 index 0000000000..6954aa3927 --- /dev/null +++ b/ci-scripts/cls_cots_ue.py @@ -0,0 +1,88 @@ +# * 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 +#--------------------------------------------------------------------- + +#to use logging.info() +import logging +#to create a SSH object locally in the methods +import sshconnection +#time.sleep +import time + +class CotsUe: + def __init__(self,model,UEIPAddr,UEUserName,UEPassWord): + self.model = model + self.UEIPAddr = UEIPAddr + self.UEUserName = UEUserName + self.UEPassWord = UEPassWord + self.runargs = '' #on of off to toggle airplane mode on/off + self.__SetAirplaneRetry = 3 + +#-----------------$ +#PUBLIC Methods$ +#-----------------$ + + def Check_Airplane(self): + mySSH = sshconnection.SSHConnection() + mySSH.open(self.UEIPAddr, self.UEUserName, self.UEPassWord) + status=mySSH.cde_check_value('sudo adb shell settings get global airplane_mode_on ', ['0','1'],5) + mySSH.close() + return status + + + def Set_Airplane(self,target_state_str): + mySSH = sshconnection.SSHConnection() + mySSH.open(self.UEIPAddr, self.UEUserName, self.UEPassWord) + mySSH.command('sudo adb start-server','$',5) + logging.info("Toggling COTS UE Airplane mode to : "+target_state_str) + current_state = self.Check_Airplane() + if target_state_str.lower()=="on": + target_state=1 + else: + target_state=0 + if current_state != target_state: + #toggle state + retry = 0 + while (current_state!=target_state) and (retry < self.__SetAirplaneRetry): + mySSH.command('sudo adb shell am start -a android.settings.AIRPLANE_MODE_SETTINGS', '\$', 5) + mySSH.command('sudo adb shell input keyevent 20', '\$', 5) + mySSH.command('sudo adb shell input tap 968 324', '\$', 5) + time.sleep(1) + current_state = self.Check_Airplane() + retry+=1 + if current_state != target_state: + logging.error("ATTENTION : Could not toggle to : "+target_state_str) + logging.error("Current state is : "+ str(current_state)) + else: + print("Airplane mode is already "+ target_state_str) + mySSH.command('sudo adb kill-server','$',5) + mySSH.close() + + + + diff --git a/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf new file mode 100755 index 0000000000..5b2c90a714 --- /dev/null +++ b/ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf @@ -0,0 +1,284 @@ +Active_eNBs = ( "eNB-Eurecom-LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + # real_time choice in {hard, rt-preempt, no} + real_time = "no"; + ////////// Identification parameters: + eNB_ID = 0xe01; + cell_type = "CELL_MACRO_ENB"; + eNB_name = "eNB-Eurecom-LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ( + { mcc = 222; mnc = 01; mnc_length = 2; } + ); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + component_carriers = ( + { + node_function = "eNodeB_3GPP"; + node_timing = "synch_to_ext_device"; + node_synch_ref = 0; + nb_antenna_ports = 1; + ue_TransmissionMode = 1; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + prach_root = 0; + tx_gain = 90; + rx_gain = 115; + pbch_repetition = "FALSE"; + + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + + pucch_delta_shift = 1; + pucch_nRB_CQI = 0; + pucch_nCS_AN = 0; + pucch_n1_AN = 0; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; +/* + srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =; +*/ + + pusch_p0_Nominal = -96; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + //Parameters for SIB18 + rxPool_sc_CP_Len = "normal"; + rxPool_sc_Period = "sf40"; + rxPool_data_CP_Len = "normal"; + rxPool_ResourceConfig_prb_Num = 20; + rxPool_ResourceConfig_prb_Start = 5; + rxPool_ResourceConfig_prb_End = 44; + rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + rxPool_ResourceConfig_offsetIndicator_choice = 0; + rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; + rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; +/* + rxPool_dataHoppingConfig_hoppingParameter = 0; + rxPool_dataHoppingConfig_numSubbands = "ns1"; + rxPool_dataHoppingConfig_rbOffset = 0; + rxPool_commTxResourceUC-ReqAllowed = "TRUE"; +*/ + // Parameters for SIB19 + discRxPool_cp_Len = "normal" + discRxPool_discPeriod = "rf32" + discRxPool_numRetx = 1; + discRxPool_numRepetition = 2; + discRxPool_ResourceConfig_prb_Num = 5; + discRxPool_ResourceConfig_prb_Start = 3; + discRxPool_ResourceConfig_prb_End = 21; + discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; + discRxPool_ResourceConfig_offsetIndicator_choice = 0; + discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; + discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; + + } + ); + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + enable_measurement_reports = "yes"; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth1"; + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + + ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="high"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="debug"; + rlc_log_verbosity ="high"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="high"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + phy_test_mode = 0; + puSch10xSnr = 160; + puCch10xSnr = 160; + } +); + +THREAD_STRUCT = ( + { + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + worker_config = "ENABLE"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 118; + eNB_instances = [0]; + clock_src = "external"; + } +); + +log_config : + { + global_log_level ="info"; + global_log_verbosity ="high"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="high"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="high"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf new file mode 100755 index 0000000000..92af74c300 --- /dev/null +++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf @@ -0,0 +1,291 @@ +Active_gNBs = ( "gNB-Eurecom-5GNRBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + cell_type = "CELL_MACRO_GNB"; + gNB_name = "gNB-Eurecom-5GNRBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;}); + + tr_s_preference = "local_mac" + + ////////// Physical parameters: + + ssb_SubcarrierOffset = 31; //0; + pdsch_AntennaPorts = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 84 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641272; //641032; #641968; 641968=start of ssb at 3600MHz + 82 RBs 641032=center of SSB at center of cell + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640000; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=84,L=13 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 0; + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + #pdschTimeDomainAllocationList (up to 16 entries) + initialDLBWPk0_0 = 0; + #initialULBWPmappingType + #0=typeA,1=typeB + initialDLBWPmappingType_0 = 0; + #this is SS=1,L=13 + initialDLBWPstartSymbolAndLength_0 = 40; + + initialDLBWPk0_1 = 0; + initialDLBWPmappingType_1 = 0; + #this is SS=2,L=12 + initialDLBWPstartSymbolAndLength_1 = 53; + + initialDLBWPk0_2 = 0; + initialDLBWPmappingType_2 = 0; + #this is SS=1,L=12 + initialDLBWPstartSymbolAndLength_2 = 54; + + initialDLBWPk0_3 = 0; + initialDLBWPmappingType_3 = 0; + #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57) + initialDLBWPstartSymbolAndLength_3 = 57; //43; //57; + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -100; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, + +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + # pusch-ConfigCommon (up to 16 elements) + initialULBWPk2_0 = 2; + initialULBWPmappingType_0 = 1 + # this is SS=0 L=11 + initialULBWPstartSymbolAndLength_0 = 55; + + initialULBWPk2_1 = 2; + initialULBWPmappingType_1 = 1; + # this is SS=0 L=12 + initialULBWPstartSymbolAndLength_1 = 69; + + initialULBWPk2_2 = 7; + initialULBWPmappingType_2 = 1; + # this is SS=10 L=4 + initialULBWPstartSymbolAndLength_2 = 52; + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; #0x80; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; //8; //7; + nrofDownlinkSymbols = 6; //0; //6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; //0; //4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + ///X2 + enable_x2 = "yes"; + t_reloc_prep = 1000; /* unit: millisecond */ + tx2_reloc_overall = 2000; /* unit: millisecond */ + target_enb_x2_ip_address = ( + { ipv4 = "CI_FR1_CTL_ENB_IP_ADDR"; + ipv6 = "192:168:30::17"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + + GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "CI_GNB_IP_ADDR"; + GNB_INTERFACE_NAME_FOR_S1U = "eth0"; + GNB_IPV4_ADDRESS_FOR_S1U = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + GNB_IPV4_ADDRESS_FOR_X2C = "CI_GNB_IP_ADDR"; + GNB_PORT_FOR_X2C = 36422; # Spec 36422 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + } +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [7]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + clock_src = "external"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_RU_L1_TRX_SPLIT"; + //parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 09d500f203..25bbbba091 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -66,38 +66,6 @@ class EPCManagement(): self.MmeIPAddress = '' self.containerPrefix = 'prod' -#----------------------------------------------------------- -# 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 - def GetMmeIPAddress(self): - return self.MmeIPAddress - def SetContainerPrefix(self, prefix): - self.containerPrefix = prefix #----------------------------------------------------------- # EPC management functions diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 8fa99fa61b..8f2d38cced 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -82,73 +82,14 @@ class HTMLManagement(): #----------------------------------------------------------- # 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 diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 63358eca38..d37f205f4e 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,15 +28,30 @@ # pexpect #--------------------------------------------------------------------- -import constants as CONST #----------------------------------------------------------- -# Import +# Import Components +#----------------------------------------------------------- + +import helpreadme as HELP +import constants as CONST + +import cls_physim #class PhySim for physical simulators build and test +import cls_cots_ue #class CotsUe for Airplane mode control + +import sshconnection +import epc +import ran +import html + + +#----------------------------------------------------------- +# Import Libs #----------------------------------------------------------- import sys # arg import re # reg -import pexpect # pexpect +import pexpect # pexpect import time # sleep import os import subprocess @@ -51,8 +66,9 @@ logging.basicConfig( ) + #----------------------------------------------------------- -# Class Declaration +# OaiCiTest Class Definition #----------------------------------------------------------- class OaiCiTest(): @@ -97,12 +113,13 @@ class OaiCiTest(): self.UEIPAddress = '' self.UEUserName = '' self.UEPassword = '' - self.UE_instance = '' + self.UE_instance = 0 self.UESourceCodePath = '' self.UELogFile = '' self.Build_OAI_UE_args = '' self.Initialize_OAI_UE_args = '' self.clean_repository = True + self.air_interface='' self.expectedNbOfConnectedUEs = 0 def BuildOAIUE(self): @@ -112,10 +129,10 @@ class OaiCiTest(): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) result = re.search('--nrUE', self.Build_OAI_UE_args) if result is not None: - RAN.Setair_interface('nr') + self.air_interface='nr-uesoftmodem' ue_prefix = 'NR ' else: - RAN.Setair_interface('lte') + self.air_interface='lte-uesoftmodem' ue_prefix = '' result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) if result is not None: @@ -155,7 +172,7 @@ class OaiCiTest(): mismatch = True if not mismatch: SSH.close() - HTML.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK) return SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) @@ -181,7 +198,7 @@ class OaiCiTest(): SSH.command('ls ran_build/build', '\$', 3) SSH.command('ls ran_build/build', '\$', 3) buildStatus = True - result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) + result = re.search(self.air_interface, SSH.getBefore()) if result is None: buildStatus = False SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) @@ -209,33 +226,33 @@ class OaiCiTest(): sys.exit(1) def CheckFlexranCtrlInstallation(self): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': return - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) 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: - RAN.SetflexranCtrlInstalled(True) + RAN.flexranCtrlInstalled=True logging.debug('Flexran Controller is installed') SSH.close() def InitializeFlexranCtrl(self): - if RAN.GetflexranCtrlInstalled() == False: + if RAN.flexranCtrlInstalled == False: return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) 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('echo ' + EPC.Password + ' | sudo -S rm -f log/*.log', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | 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') - RAN.SetflexranCtrlStarted(True) + RAN.flexranCtrlStarted=True SSH.close() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) @@ -306,14 +323,14 @@ class OaiCiTest(): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - if RAN.Getair_interface() == 'lte': + if self.air_interface == 'lte-uesoftmodem': 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): - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', pStatus) HTML.CreateHtmlTabFooter(False) sys.exit(1) UE_prefix = '' @@ -335,7 +352,7 @@ class OaiCiTest(): # Initialize_OAI_UE_args usually start with -C and followed by the location in repository SSH.command('source oaienv', '\$', 5) SSH.command('cd cmake_targets/ran_build/build', '\$', 5) - if RAN.Getair_interface() == 'lte': + if self.air_interface == 'lte-uesoftmodem': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) # We may have to regenerate the .u* files if result is None: @@ -351,13 +368,13 @@ class OaiCiTest(): SSH.command('if [ -e rbconfig.raw ]; then echo ' + self.UEPassword + ' | sudo -S rm rbconfig.raw; fi', '\$', 5) SSH.command('if [ -e reconfig.raw ]; then echo ' + self.UEPassword + ' | sudo -S rm reconfig.raw; fi', '\$', 5) # Copy the RAW files from gNB running directory (maybe on another machine) - copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/rbconfig.raw', '.') + copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/rbconfig.raw', '.') if (copyin_res == 0): SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './rbconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build') - copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/reconfig.raw', '.') + copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/reconfig.raw', '.') if (copyin_res == 0): SSH.copyout(self.UEIPAddress, self.UEUserName, self.UEPassword, './reconfig.raw', self.UESourceCodePath + '/cmake_targets/ran_build/build') - SSH.command('echo "ulimit -c unlimited && ./'+ RAN.Getair_interface() +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo "ulimit -c unlimited && ./'+ self.air_interface +' ' + self.Initialize_OAI_UE_args + '" > ./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' @@ -370,9 +387,7 @@ class OaiCiTest(): while (doOutterLoop): 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 - #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) + SSH.command('echo $USER; nohup sudo -E ./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) SSH.command('cd ../..', '\$', 5) doLoop = True @@ -388,7 +403,7 @@ class OaiCiTest(): doLoop = False continue SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': result = re.search('Starting sync detection', SSH.getBefore()) else: result = re.search('got sync', SSH.getBefore()) @@ -413,7 +428,7 @@ class OaiCiTest(): # That is the case for LTE # In NR case, it's a positive message that will show if synchronization occurs doLoop = True - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': loopCounter = 10 else: # We are now checking if sync w/ eNB DOES NOT OCCUR @@ -422,7 +437,7 @@ class OaiCiTest(): while (doLoop): loopCounter = loopCounter - 1 if (loopCounter == 0): - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': # Here we do have great chances that UE did NOT cell-sync w/ gNB doLoop = False fullSyncStatus = False @@ -441,7 +456,7 @@ class OaiCiTest(): fullSyncStatus = True continue SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Frequency"', '\$', 4) - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': # Positive messaging --> result = re.search('Measured Carrier Frequency', SSH.getBefore()) if result is not None: @@ -470,12 +485,12 @@ class OaiCiTest(): if fullSyncStatus and gotSyncStatus: doInterfaceCheck = False - if RAN.Getair_interface() == 'lte': + if self.air_interface == 'lte-uesoftmodem': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) if result is None: doInterfaceCheck = True # For the moment, only in explicit noS1 without kernel module (ie w/ tunnel interface) - if RAN.Getair_interface() == 'nr': + if self.air_interface == 'nr-uesoftmodem': result = re.search('--noS1 --nokrnmod 1', str(self.Initialize_OAI_UE_args)) if result is not None: doInterfaceCheck = True @@ -491,7 +506,7 @@ class OaiCiTest(): logging.debug(SSH.getBefore()) logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') tunnelInterfaceStatus = False - if RAN.GeteNBmbmsEnable(0): + if RAN.eNBmbmsEnables[0]: SSH.command('ifconfig oaitun_uem1', '\$', 4) result = re.search('inet addr', SSH.getBefore()) if result is not None: @@ -507,7 +522,7 @@ class OaiCiTest(): SSH.close() if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.air_interface + ' ' + 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 = [] @@ -515,15 +530,15 @@ class OaiCiTest(): self.UEDevicesStatus = [] self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) else: - if RAN.Getair_interface() == 'lte': - if RAN.GeteNBmbmsEnable(0): - HTML.SethtmlUEFailureMsg('oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured') + if self.air_interface == 'lte-uesoftmodem': + if RAN.eNBmbmsEnables[0]: + HTML.htmlUEFailureMsg='oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' else: - 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') + HTML.htmlUEFailureMsg='oaitun_ue1 interface is either NOT mounted or NOT configured' + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') else: - HTML.SethtmlUEFailureMsg('nr-uesoftmodem did NOT synced') - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') + HTML.htmlUEFailureMsg='nr-uesoftmodem did NOT synced' + HTML.CreateHtmlTestRow(self.air_interface + ' ' + self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') logging.error('\033[91mInitialize OAI UE Failed! \033[0m') self.AutoTerminateUEandeNB() @@ -675,7 +690,7 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() def PingCatM(self): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True @@ -688,10 +703,10 @@ class OaiCiTest(): try: statusQueue = SimpleQueue() lock = Lock() - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) - if re.match('OAI', EPC.GetType(), re.IGNORECASE): + if re.match('OAI', EPC.Type, re.IGNORECASE): logging.debug('Using the OAI EPC HSS: not implemented yet') HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) HTML.CreateHtmlTabFooter(False) @@ -891,7 +906,7 @@ class OaiCiTest(): self.UEDevicesStatus[cnt] = CONST.UE_STATUS_ATTACHED cnt += 1 HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + result = re.search('T_stdout', str(RAN.Initialize_eNB_args)) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) @@ -937,7 +952,7 @@ class OaiCiTest(): for job in multi_jobs: job.join() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + result = re.search('T_stdout', str(RAN.Initialize_eNB_args)) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) @@ -1071,7 +1086,6 @@ class OaiCiTest(): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: 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: @@ -1203,8 +1217,8 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) SSH.command('cd /opt/flexran_rtc', '\$', 5) SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) @@ -1316,13 +1330,13 @@ class OaiCiTest(): # 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', EPC.GetType(), re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): launchFromEpc = False ping_time = re.findall("-c (\d+)",str(self.ping_args)) if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 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: @@ -1331,9 +1345,9 @@ class OaiCiTest(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) ping_status = ret.returncode - 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) + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cat ' + EPC.SourceCodePath + '/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!' @@ -1413,7 +1427,7 @@ class OaiCiTest(): return ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) if ping_from_eNB is not None: - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') else: @@ -1422,8 +1436,8 @@ class OaiCiTest(): sys.exit('Insufficient Parameter') try: if ping_from_eNB is not None: - SSH.open(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword()) - SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets/', '\$', 5) + SSH.open(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword) + SSH.command('cd ' + RAN.eNBSourceCodePath + '/cmake_targets/', '\$', 5) else: SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) @@ -1487,20 +1501,20 @@ class OaiCiTest(): # copying on the EPC server for logCollection if ping_from_eNB is not None: - copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + copyin_res = SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') else: copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') if (copyin_res == 0): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'ping_' + self.testCase_id + '.log', EPC.SourceCodePath + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) def Ping(self): - result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) + result = re.search('noS1', str(RAN.Initialize_eNB_args)) if result is not None: self.PingNoS1() return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True @@ -1586,7 +1600,7 @@ class OaiCiTest(): return result def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - SSH.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('awk -f /tmp/tcp_iperf_stats.awk ' + EPC.SourceCodePath + '/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') @@ -1844,7 +1858,7 @@ class OaiCiTest(): # 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', EPC.GetType(), re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): launchFromEpc = False cmd = 'hostname -I' ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') @@ -1852,13 +1866,13 @@ class OaiCiTest(): EPC_Iperf_UE_IPAddress = ret.stdout.strip() port = 5001 + idx if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if udpIperf: - SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) + SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) else: - SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) + SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.UserName, 5) SSH.close() else: if self.ueIperfVersion == self.dummyIperfVersion: @@ -1881,7 +1895,7 @@ class OaiCiTest(): SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) else: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.command('cd ' + EPC.SourceCodePath+ '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -1915,27 +1929,27 @@ class OaiCiTest(): # Kill iperf server on EPC side if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('killall --signal SIGKILL iperf', EPC.GetUserName(), 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('killall --signal SIGKILL iperf', EPC.UserName, 5) SSH.close() else: cmd = 'killall --signal SIGKILL iperf' logging.debug(cmd) subprocess.run(cmd, shell=True) time.sleep(1) - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') # in case of failure, retrieve server log if (clientStatus == -1) or (clientStatus == -2): 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') - SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath+ '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI-UE if (device_id == 'OAI-UE'): 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') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: @@ -1949,8 +1963,8 @@ class OaiCiTest(): if (device_id != 'OAI-UE'): 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 - SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + EPC.GetSourceCodePath() + '/scripts ; fi', '\$', 5) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.command('if [ ! -d ' + EPC.SourceCodePath + '/scripts ]; then mkdir -p ' + EPC.SourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) # Checking if iperf / iperf3 are installed if self.ADBCentralized: SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) @@ -2009,7 +2023,7 @@ class OaiCiTest(): 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: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) if self.ADBCentralized: if (useIperf3): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) @@ -2031,11 +2045,11 @@ class OaiCiTest(): # 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', EPC.GetType(), re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.Type, re.IGNORECASE): launchFromEpc = False if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2070,9 +2084,9 @@ class OaiCiTest(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) iperf_status = ret.returncode - 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) + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cat ' + EPC.SourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if iperf_status < 0: if launchFromEpc: SSH.close() @@ -2109,7 +2123,7 @@ class OaiCiTest(): if (device_id == 'OAI-UE'): SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') else: - SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.SourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') # fromdos has to be called on the python executor not on ADB server cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log' subprocess.run(cmd, shell=True) @@ -2119,15 +2133,15 @@ class OaiCiTest(): if (device_id == 'OAI-UE'): if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): if not launchFromEpc: - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') else: 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') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.SourceCodePath + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) def IperfNoS1(self): - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True @@ -2139,9 +2153,9 @@ class OaiCiTest(): return server_on_enb = re.search('-R', str(self.iperf_args)) if server_on_enb is not None: - iServerIPAddr = RAN.GeteNBIPAddress() - iServerUser = RAN.GeteNBUserName() - iServerPasswd = RAN.GeteNBPassword() + iServerIPAddr = RAN.eNBIPAddress + iServerUser = RAN.eNBUserName + iServerPasswd = RAN.eNBPassword iClientIPAddr = self.UEIPAddress iClientUser = self.UEUserName iClientPasswd = self.UEPassword @@ -2149,9 +2163,9 @@ class OaiCiTest(): iServerIPAddr = self.UEIPAddress iServerUser = self.UEUserName iServerPasswd = self.UEPassword - iClientIPAddr = RAN.GeteNBIPAddress() - iClientUser = RAN.GeteNBUserName() - iClientPasswd = RAN.GeteNBPassword() + iClientIPAddr = RAN.eNBIPAddress + iClientUser = RAN.eNBUserName + iClientPasswd = RAN.eNBPassword if self.iperf_options != 'sink': # Starting the iperf server SSH.open(iServerIPAddr, iServerUser, iServerPasswd) @@ -2206,10 +2220,10 @@ class OaiCiTest(): if (clientStatus == -1): 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): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.SourceCodePath + '/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): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.SourceCodePath + '/scripts') iperf_noperf = False if status_queue.empty(): iperf_status = False @@ -2236,11 +2250,11 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() def Iperf(self): - result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) + result = re.search('noS1', str(RAN.Initialize_eNB_args)) if result is not None: self.IperfNoS1() return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True @@ -2317,7 +2331,7 @@ class OaiCiTest(): 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(RAN.GetInitialize_eNB_args())) + result = re.search('noS1|band78', str(RAN.Initialize_eNB_args)) if result is None: p = Process(target = EPC.CheckHSSProcess, args = (status_queue,)) p.daemon = True @@ -2356,14 +2370,14 @@ class OaiCiTest(): if (status < 0): result = status if result == CONST.ENB_PROCESS_FAILED: - fileCheck = re.search('enb_', str(RAN.GeteNBLogFile(0))) + fileCheck = re.search('enb_', str(RAN.eNBLogFiles[0])) if fileCheck is not None: - SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFile(0), '.') - logStatus = RAN.AnalyzeLogFile_eNB(RAN.GeteNBLogFile[0]) + SSH.copyin(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath + '/cmake_targets/' + RAN.eNBLogFiles[0], '.') + logStatus = RAN.AnalyzeLogFile_eNB(RAN.eNBLogFiles[0]) if logStatus < 0: result = logStatus - RAN.SeteNBLogFile('', 0) - if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): + RAN.eNBLogFiles[0]='' + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: self.TerminateFlexranCtrl() return result @@ -2398,8 +2412,8 @@ class OaiCiTest(): def CheckOAIUEProcess(self, status_queue): try: 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()) + SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + ' | grep -v grep', '\$', 5) + result = re.search(self.air_interface, SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') status_queue.put(CONST.OAI_UE_PROCESS_FAILED) @@ -2436,7 +2450,7 @@ class OaiCiTest(): nrFoundDCI = 0 nrCRCOK = 0 mbms_messages = 0 - HTML.SethtmlUEFailureMsg('') + HTML.htmlUEFailureMsg='' global_status = CONST.ALL_PROCESSES_OK for line in ue_log_file.readlines(): result = re.search('nr_synchro_time', str(line)) @@ -2498,7 +2512,7 @@ class OaiCiTest(): result = re.search('No cell synchronization found, abandoning', str(line)) if result is not None: no_cell_sync_found = True - if RAN.GeteNBmbmsEnable(0): + if RAN.eNBmbmsEnables[0]: result = re.search('TRIED TO PUSH MBMS DATA', str(line)) if result is not None: mbms_messages += 1 @@ -2506,22 +2520,22 @@ class OaiCiTest(): if result is not None and (not mib_found): try: mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " nidcell = " + result.group('nidcell') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg) + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " n_rb_dl = " + result.group('n_rb_dl') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " phich_duration = " + result.group('phich_duration') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg) + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " phich_resource = " + result.group('phich_resource') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " tx_ant = " + result.group('tx_ant') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') mib_found = True except Exception as e: @@ -2530,7 +2544,7 @@ class OaiCiTest(): if result is not None and (not frequency_found): try: mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') frequency_found = True except Exception as e: @@ -2539,7 +2553,7 @@ class OaiCiTest(): if result is not None and (not plmn_found): try: mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') plmn_found = True except Exception as e: @@ -2548,7 +2562,7 @@ class OaiCiTest(): if result is not None: try: mibMsg = "The operator is: " + result.group('operator') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + '\n' logging.debug('\033[94m' + mibMsg + '\033[0m') except Exception as e: logging.error('\033[91m' + "Operator name not found" + '\033[0m') @@ -2556,7 +2570,7 @@ class OaiCiTest(): if result is not None: try: mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + ' -> ') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + mibMsg + ' -> ' logging.debug('\033[94m' + mibMsg + '\033[0m') except Exception as e: logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') @@ -2566,7 +2580,7 @@ class OaiCiTest(): freq = result.group('carrier_frequency') new_freq = re.sub('/[0-9]+','',freq) float_freq = float(new_freq) / 1000000 - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' logging.debug('\033[94m' + " DL Carrier Frequency is: " + str(freq) + '\033[0m') except Exception as e: logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') @@ -2574,7 +2588,7 @@ class OaiCiTest(): if result is not None: try: prb = result.group('allowed_bandwidth') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + ' -- PRB: ' + prb + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + ' -- PRB: ' + prb + '\n' logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') except Exception as e: logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') @@ -2582,57 +2596,57 @@ class OaiCiTest(): if rrcConnectionRecfgComplete > 0: statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' logging.debug('\033[94m' + statMsg + '\033[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 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') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if nrFoundDCI > 0: statMsg = 'UE showed ' + str(nrFoundDCI) + ' DCI found message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if nrCRCOK > 0: statMsg = 'UE showed ' + str(nrCRCOK) + ' PDSCH decoding message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if not frequency_found: statMsg = 'NR-UE could NOT synch!' logging.error('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if uciStatMsgCount > 0: statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 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') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 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') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 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') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if fatalErrorCount > 0: statMsg = 'UE showed ' + str(fatalErrorCount) + ' "FATAL ERROR:" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 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') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') - if RAN.GeteNBmbmsEnable(0): + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' + if RAN.eNBmbmsEnables[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') - global_status = OAI_UE_PROCESS_NO_MBMS_MSGS - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') + global_status = CONST.OAI_UE_PROCESS_NO_MBMS_MSGS + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + statMsg + '\n' if foundSegFault: logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') if not nrUEFlag: @@ -2642,7 +2656,7 @@ class OaiCiTest(): global_status = CONST.OAI_UE_PROCESS_SEG_FAULT if foundAssertion: logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE showed an assertion!\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE showed an assertion!\n' if not nrUEFlag: if not mib_found or not frequency_found: global_status = CONST.OAI_UE_PROCESS_ASSERTION @@ -2651,31 +2665,31 @@ class OaiCiTest(): global_status = CONST.OAI_UE_PROCESS_ASSERTION if foundRealTimeIssue: logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE faced real time issues!\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE faced real time issues!\n' if nrUEFlag: if not frequency_found: global_status = 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') - HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE could not synchronize!\n') + HTML.htmlUEFailureMsg=HTML.htmlUEFailureMsg + 'UE could not synchronize!\n' global_status = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return global_status def TerminateFlexranCtrl(self): - if RAN.GetflexranCtrlInstalled() == False or RAN.GetflexranCtrlStarted() == False: + if RAN.flexranCtrlInstalled == False or RAN.flexranCtrlStarted == False: return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('echo ' + EPC.Password + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) time.sleep(1) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + SSH.command('echo ' + EPC.Password + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) time.sleep(1) SSH.close() - RAN.SetflexranCtrlStarted(False) + RAN.flexranCtrlStarted=False HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateUE_common(self, device_id, idx): @@ -2741,7 +2755,7 @@ class OaiCiTest(): 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') - HTML.SethtmlUEFailureMsg('Could not copy UE logfile to analyze it!') + HTML.htmlUEFailureMsg='Could not copy UE logfile to analyze it!' HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') self.UELogFile = '' return @@ -2754,9 +2768,9 @@ class OaiCiTest(): ueAction = 'Connection' if (logStatus < 0): logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') - HTML.SethtmlUEFailureMsg('' + ueAction + ' Failed\n' + HTML.GethtmlUEFailureMsg()) + HTML.htmlUEFailureMsg='' + ueAction + ' Failed\n' + HTML.htmlUEFailureMsg HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') - if RAN.Getair_interface() == 'lte': + if self.air_interface == 'lte-uesoftmodem': # In case of sniffing on commercial eNBs we have random results # Not an error then if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): @@ -2768,7 +2782,7 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() else: logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') - HTML.SethtmlUEFailureMsg('' + ueAction + ' Completed\n' + HTML.GethtmlUEFailureMsg()) + HTML.htmlUEFailureMsg='' + ueAction + ' Completed\n' + HTML.htmlUEFailureMsg HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.UELogFile = '' else: @@ -2777,41 +2791,41 @@ class OaiCiTest(): def AutoTerminateUEandeNB(self): if (self.ADBIPAddress != 'none'): self.testCase_id = 'AUTO-KILL-UE' - HTML.SettestCase_id(self.testCase_id) + HTML.testCase_id=self.testCase_id self.desc = 'Automatic Termination of UE' - HTML.Setdesc('Automatic Termination of UE') + HTML.desc='Automatic Termination of UE' self.ShowTestID() self.TerminateUE() if (self.Initialize_OAI_UE_args != ''): self.testCase_id = 'AUTO-KILL-OAI-UE' - HTML.SettestCase_id(self.testCase_id) + HTML.testCase_id=self.testCase_id self.desc = 'Automatic Termination of OAI-UE' - HTML.Setdesc('Automatic Termination of OAI-UE') + HTML.desc='Automatic Termination of OAI-UE' self.ShowTestID() self.TerminateOAIUE() - if (RAN.GetInitialize_eNB_args() != ''): + if (RAN.Initialize_eNB_args != ''): self.testCase_id = 'AUTO-KILL-eNB' - HTML.SettestCase_id(self.testCase_id) + HTML.testCase_id=self.testCase_id self.desc = 'Automatic Termination of eNB' - HTML.Setdesc('Automatic Termination of eNB') + HTML.desc='Automatic Termination of eNB' self.ShowTestID() - RAN.SeteNB_instance('0') + RAN.eNB_instance=0 RAN.TerminateeNB() - if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: self.testCase_id = 'AUTO-KILL-flexran-ctl' - HTML.SettestCase_id(self.testCase_id) + HTML.testCase_id=self.testCase_id self.desc = 'Automatic Termination of FlexRan CTL' - HTML.Setdesc('Automatic Termination of FlexRan CTL') + HTML.desc='Automatic Termination of FlexRan CTL' self.ShowTestID() self.TerminateFlexranCtrl() - RAN.SetprematureExit(True) + RAN.prematureExit=True def IdleSleep(self): time.sleep(self.idle_sleep_time) HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', CONST.ALL_PROCESSES_OK) def X2_Status(self, idx, fileName): - cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName + cmd = "curl --silent http://" + EPC.IPAddress + ":9999/stats | jq '.' > " + fileName message = cmd + '\n' logging.debug(cmd) subprocess.run(cmd, shell=True) @@ -2860,7 +2874,7 @@ class OaiCiTest(): logging.debug(msg) fullMessage += msg + '\n' if self.x2_ho_options == 'network': - if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): + if RAN.flexranCtrlInstalled and RAN.flexranCtrlStarted: self.x2ENBBsIds = [] self.x2ENBConnectedUEs = [] self.x2ENBBsIds.append([]) @@ -2875,7 +2889,7 @@ class OaiCiTest(): eNB_cnt = self.x2NbENBs cnt = 0 while cnt < eNB_cnt: - cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" + cmd = "curl -XPOST http://" + EPC.IPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) @@ -2889,7 +2903,7 @@ class OaiCiTest(): while cnt < eNB_cnt: ueIdx = 0 while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]): - 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]) + cmd = "curl -XPOST http://" + EPC.IPAddress() + ":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) @@ -2921,11 +2935,11 @@ class OaiCiTest(): HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', CONST.ALL_PROCESSES_OK) def LogCollectBuild(self): - if (RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != ''): - IPAddress = RAN.GeteNBIPAddress() - UserName = RAN.GeteNBUserName() - Password = RAN.GeteNBPassword() - SourceCodePath = RAN.GeteNBSourceCodePath() + if (RAN.eNBIPAddress != '' and RAN.eNBUserName != '' and RAN.eNBPassword != ''): + IPAddress = RAN.eNBIPAddress + UserName = RAN.eNBUserName + Password = RAN.eNBPassword + SourceCodePath = RAN.eNBSourceCodePath elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): IPAddress = self.UEIPAddress UserName = self.UEUserName @@ -2940,8 +2954,8 @@ class OaiCiTest(): SSH.command('zip build.log.zip build_log_*/*', '\$', 60) SSH.close() def LogCollectPing(self): - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) SSH.command('rm -f ping.log.zip', '\$', 5) SSH.command('zip ping.log.zip ping*.log', '\$', 60) @@ -2949,8 +2963,8 @@ class OaiCiTest(): SSH.close() def LogCollectIperf(self): - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.open(EPC.IPAddress, EPC.UserName, EPC.Password) + SSH.command('cd ' + EPC.SourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) SSH.command('rm -f iperf.log.zip', '\$', 5) SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) @@ -2967,20 +2981,20 @@ class OaiCiTest(): SSH.close() def RetrieveSystemVersion(self, machine): - 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) + if RAN.eNBIPAddress == 'none' or self.UEIPAddress == 'none': + HTML.OsVersion[0]='Ubuntu 16.04.5 LTS' + HTML.KernelVersion[0]='4.15.0-45-generic' + HTML.UhdVersion[0]='3.13.0.1-0' + HTML.UsrpBoard[0]='B210' + HTML.CpuNb[0]='4' + HTML.CpuModel[0]='Intel(R) Core(TM) i5-6200U' + HTML.CpuMHz[0]='2399.996 MHz' return 0 if machine == 'eNB': - if RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != '': - IPAddress = RAN.GeteNBIPAddress() - UserName = RAN.GeteNBUserName() - Password = RAN.GeteNBPassword() + if RAN.eNBIPAddress != '' and RAN.eNBUserName != '' and RAN.eNBPassword != '': + IPAddress = RAN.eNBIPAddress + UserName = RAN.eNBUserName + Password = RAN.eNBPassword idx = 0 else: return -1 @@ -2999,7 +3013,7 @@ class OaiCiTest(): if result is not None: OsVersion = result.group('os_type') logging.debug('OS is: ' + OsVersion) - HTML.SetOsVersion(OsVersion, idx) + HTML.OsVersion[idx]=OsVersion else: SSH.command('hostnamectl', '\$', 5) result = re.search('Operating System: (?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) @@ -3011,26 +3025,26 @@ class OaiCiTest(): if result is not None: OsVersion = OsVersion.replace('7 ', result.group('os_version')) logging.debug('OS is: ' + OsVersion) - HTML.SetOsVersion(OsVersion, idx) + HTML.OsVersion[idx]=OsVersion SSH.command('uname -r', '\$', 5) result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', SSH.getBefore()) if result is not None: KernelVersion = result.group('kernel_version') logging.debug('Kernel Version is: ' + KernelVersion) - HTML.SetKernelVersion(KernelVersion, idx) + HTML.KernelVersion[idx]=KernelVersion SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', SSH.getBefore()) if result is not None: UhdVersion = result.group('uhd_version') logging.debug('UHD Version is: ' + UhdVersion) - HTML.SetUhdVersion(UhdVersion, idx) + HTML.UhdVersion[idx]=UhdVersion else: SSH.command('uhd_config_info --version', '\$', 5) result = re.search('UHD (?P[a-zA-Z0-9\.\-]+)', SSH.getBefore()) if result is not None: UhdVersion = result.group('uhd_version') logging.debug('UHD Version is: ' + UhdVersion) - HTML.SetUhdVersion(UhdVersion, idx) + HTML.UhdVersion[idx]=UhdVersion 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 @@ -3042,99 +3056,132 @@ class OaiCiTest(): count += 1 if count > 0: logging.debug('USRP Board(s) : ' + UsrpBoard) - HTML.SetUsrpBoard(UsrpBoard, idx) + HTML.UsrpBoard[idx]=UsrpBoard 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: CpuNb = result.group('nb_cpus') logging.debug('nb_cpus: ' + CpuNb) - HTML.SetCpuNb(CpuNb, idx) + HTML.CpuNb[idx]=CpuNb CpuModel = result.group('model') logging.debug('model: ' + CpuModel) - HTML.SetCpuModel(CpuModel, idx) + HTML.CpuModel[idx]=CpuModel CpuMHz = result.group('cpu_mhz') + ' MHz' logging.debug('cpu_mhz: ' + CpuMHz) - HTML.SetCpuMHz(CpuMHz, idx) + HTML.CpuMHz[idx]=CpuMHz SSH.close() -#----------------------------------------------------------- -# ShowTestID() -#----------------------------------------------------------- def ShowTestID(self): logging.debug('\u001B[1m----------------------------------------\u001B[0m') logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') logging.debug('\u001B[1m' + self.desc + '\u001B[0m') logging.debug('\u001B[1m----------------------------------------\u001B[0m') -def CheckClassValidity(action,id): - if action!='Build_PhySim' and action!='Run_PhySim' and 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) - return False - return True + + +#----------------------------------------------------------- +# General Functions +#----------------------------------------------------------- + + + +def CheckClassValidity(xml_class_list,action,id): + if action not in xml_class_list: + logging.debug('ERROR: test-case ' + id + ' has unlisted class ' + action + ' ##CHECK xml_class_list.yml') + resp=False + else: + resp=True + return resp + + +#assigning parameters to object instance attributes (even if the attributes do not exist !!) +def AssignParams(params_dict): + + for key,value in params_dict.items(): + setattr(CiTestObj, key, value) + setattr(RAN, key, value) + setattr(HTML, key, value) + setattr(ldpc, key, value) + + def GetParametersFromXML(action): if action == 'Build_eNB': - RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) + RAN.Build_eNB_args=test.findtext('Build_eNB_args') forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') if (forced_workspace_cleanup is None): - RAN.SetBuild_eNB_forced_workspace_cleanup(False) + RAN.Build_eNB_forced_workspace_cleanup=False else: if re.match('true', forced_workspace_cleanup, re.IGNORECASE): - RAN.SetBuild_eNB_forced_workspace_cleanup(True) + RAN.Build_eNB_forced_workspace_cleanup=True else: - 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') + RAN.Build_eNB_forced_workspace_cleanup=False + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + RAN.eNB_instance=0 + else: + RAN.eNB_instance=int(eNB_instance) + RAN.eNB_serverId=test.findtext('eNB_serverId') + if (RAN.eNB_serverId is None): + RAN.eNB_serverId='0' xmlBgBuildField = test.findtext('backgroundBuild') if (xmlBgBuildField is None): - RAN.SetbackgroundBuild(False) + RAN.backgroundBuild=False else: if re.match('true', xmlBgBuildField, re.IGNORECASE): - RAN.SetbackgroundBuild(True) + RAN.backgroundBuild=True else: - RAN.SetbackgroundBuild(False) + RAN.backgroundBuild=False if action == 'WaitEndBuild_eNB': - 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') + RAN.Build_eNB_args=test.findtext('Build_eNB_args') + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + RAN.eNB_instance=0 + else: + RAN.eNB_instance=int(eNB_instance) + RAN.eNB_serverId=test.findtext('eNB_serverId') + if (RAN.eNB_serverId is None): + RAN.eNB_serverId='0' if action == 'Initialize_eNB': - 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' + RAN.Initialize_eNB_args=test.findtext('Initialize_eNB_args') + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + RAN.eNB_instance=0 else: - CiTestObj.air_interface = CiTestObj.air_interface.lower() - RAN.Setair_interface(CiTestObj.air_interface) + RAN.eNB_instance=int(eNB_instance) + RAN.eNB_serverId=test.findtext('eNB_serverId') + if (RAN.eNB_serverId is None): + RAN.eNB_serverId='0' + + #local variable air_interface + air_interface = test.findtext('air_interface') + if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): + RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem' + elif (air_interface.lower() in ['nr','lte']): + RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem' + else : + RAN.air_interface[RAN.eNB_instance] = 'ocp-enb' if action == 'Terminate_eNB': - 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' + eNB_instance=test.findtext('eNB_instance') + if (eNB_instance is None): + RAN.eNB_instance=0 else: - CiTestObj.air_interface = CiTestObj.air_interface.lower() - RAN.Setair_interface(CiTestObj.air_interface) + RAN.eNB_instance=int(eNB_instance) + RAN.eNB_serverId=test.findtext('eNB_serverId') + if (RAN.eNB_serverId is None): + RAN.eNB_serverId='0' + + #local variable air_interface + air_interface = test.findtext('air_interface') + if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): + RAN.air_interface[RAN.eNB_instance] = 'lte-softmodem' + elif (air_interface.lower() in ['nr','lte']): + RAN.air_interface[RAN.eNB_instance] = air_interface.lower() +'-softmodem' + else : + RAN.air_interface[RAN.eNB_instance] = 'ocp-enb' if action == 'Attach_UE': nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') @@ -3160,19 +3207,38 @@ def GetParametersFromXML(action): if action == 'Initialize_OAI_UE': 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' + UE_instance = test.findtext('UE_instance') + if (UE_instance is None): + CiTestObj.UE_instance = 0 else: - CiTestObj.air_interface = CiTestObj.air_interface.lower() + CiTestObj.UE_instance = UE_instance + + #local variable air_interface + air_interface = test.findtext('air_interface') + if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): + CiTestObj.air_interface = 'lte-uesoftmodem' + elif (air_interface.lower() in ['nr','lte']): + CiTestObj.air_interface = air_interface.lower() +'-uesoftmodem' + else : + #CiTestObj.air_interface = 'ocp-enb' + logging.error('OCP UE -- NOT SUPPORTED') if action == 'Terminate_OAI_UE': - RAN.SeteNB_instance(test.findtext('UE_instance')) - if (CiTestObj.UE_instance is None): + UE_instance=test.findtext('UE_instance') + if (UE_instance is None): CiTestObj.UE_instance = '0' + else: + CiTestObj.UE_instance = int(UE_instance) + + #local variable air_interface + air_interface = test.findtext('air_interface') + if (air_interface is None) or (air_interface.lower() not in ['nr','lte','ocp']): + CiTestObj.air_interface = 'lte-uesoftmodem' + elif (air_interface.lower() in ['nr','lte']): + CiTestObj.air_interface = air_interface.lower() +'-uesoftmodem' + else : + #CiTestObj.air_interface = 'ocp-enb' + logging.error('OCP UE -- NOT SUPPORTED') if action == 'Ping' or action == 'Ping_CatM_module': CiTestObj.ping_args = test.findtext('ping_args') @@ -3227,6 +3293,9 @@ def GetParametersFromXML(action): if action == 'Run_PhySim': ldpc.runargs = test.findtext('physim_run_args') + + if action == 'COTS_UE_Airplane': + COTS_UE.runargs = test.findtext('cots_ue_airplane_args') #check if given test is in list #it is in list if one of the strings in 'list' is at the beginning of 'test' @@ -3240,207 +3309,88 @@ def test_in_list(test, list): def receive_signal(signum, frame): sys.exit(1) -#----------------------------------------------------------- -# Parameter Check -#----------------------------------------------------------- -mode = '' -CiTestObj = OaiCiTest() -import sshconnection -import epc -import helpreadme as HELP -import ran -import html -import constants + + + + +#----------------------------------------------------------- +# MAIN PART +#----------------------------------------------------------- + +#loading xml action list from yaml +import yaml +xml_class_list_file='' +if (os.path.isfile('xml_class_list.yml')): + xml_class_list_file='xml_class_list.yml' +if (os.path.isfile('ci-scripts/xml_class_list.yml')): + xml_class_list_file='ci-scripts/xml_class_list.yml' +with open(xml_class_list_file,'r') as file: + # The FullLoader parameter handles the conversion from YAML + # scalar values to Python the dictionary format + xml_class_list = yaml.load(file,Loader=yaml.FullLoader) + +mode = '' + +CiTestObj = OaiCiTest() SSH = sshconnection.SSHConnection() EPC = epc.EPCManagement() RAN = ran.RANManagement() HTML = html.HTMLManagement() -EPC.SetHtmlObj(HTML) -RAN.SetHtmlObj(HTML) -RAN.SetEpcObj(EPC) +EPC.htmlObj=HTML +RAN.htmlObj=HTML +RAN.epcObj=EPC + -import cls_physim #class PhySim for physical simulators build and test ldpc=cls_physim.PhySim() #create an instance for LDPC test using GPU or CPU build -argvs = sys.argv -argc = len(argvs) + + +#----------------------------------------------------------- +# Parsing Command Line Arguments +#----------------------------------------------------------- + +import args_parse +py_param_file_present, py_params, mode = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,EPC,ldpc,HELP) + + + +#----------------------------------------------------------- +# TEMPORARY params management +#----------------------------------------------------------- +#temporary solution for testing: +if py_param_file_present == True: + AssignParams(py_params) + +#for debug +#print(RAN.__dict__) +#print(CiTestObj.__dict__) +#print(HTML.__dict__) +#print(ldpc.__dict__) +#for debug + + +#----------------------------------------------------------- +# COTS UE instanciation +#----------------------------------------------------------- +#COTS_UE instanciation can only be done here for the moment, due to code architecture +COTS_UE=cls_cots_ue.CotsUe('oppo', CiTestObj.UEIPAddress, CiTestObj.UEUserName,CiTestObj.UEPassword) + + +#----------------------------------------------------------- +# XML class (action) analysis +#----------------------------------------------------------- cwd = os.getcwd() -while len(argvs) > 1: - myArgv = argvs.pop(1) # 0th is this file's name - - if re.match('^\-\-help$', myArgv, re.IGNORECASE): - HELP.GenericHelp(CONST.Version) - sys.exit(0) - elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) - mode = matchReg.group(1) - elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ranRepository = matchReg.group(1) - RAN.SetranRepository(matchReg.group(1)) - HTML.SetranRepository(matchReg.group(1)) - ldpc.ranRepository=matchReg.group(1) - elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) - doMerge = matchReg.group(1) - ldpc.ranAllowMerge=matchReg.group(1) - if ((doMerge == 'true') or (doMerge == '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) - CiTestObj.ranBranch = matchReg.group(1) - RAN.SetranBranch(matchReg.group(1)) - HTML.SetranBranch(matchReg.group(1)) - ldpc.ranBranch=matchReg.group(1) - elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) - CiTestObj.ranCommitID = matchReg.group(1) - RAN.SetranCommitID(matchReg.group(1)) - HTML.SetranCommitID(matchReg.group(1)) - ldpc.ranCommitID=matchReg.group(1) - elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) - CiTestObj.ranTargetBranch = matchReg.group(1) - RAN.SetranTargetBranch(matchReg.group(1)) - HTML.SetranTargetBranch(matchReg.group(1)) - ldpc.ranTargetBranch=matchReg.group(1) - elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBIPAddress(matchReg.group(1)) - ldpc.eNBIpAddr=matchReg.group(1) - elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1IPAddress(matchReg.group(1)) - elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - 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) - RAN.SeteNBUserName(matchReg.group(1)) - ldpc.eNBUserName=matchReg.group(1) - elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1UserName(matchReg.group(1)) - elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - 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) - RAN.SeteNBPassword(matchReg.group(1)) - ldpc.eNBPassWord=matchReg.group(1) - elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1Password(matchReg.group(1)) - elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - 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) - RAN.SeteNBSourceCodePath(matchReg.group(1)) - ldpc.eNBSourceCodePath=matchReg.group(1) - elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1SourceCodePath(matchReg.group(1)) - elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2SourceCodePath(matchReg.group(1)) - elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) - EPC.SetIPAddress(matchReg.group(1)) - elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) - EPC.SetUserName(matchReg.group(1)) - elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) - EPC.SetPassword(matchReg.group(1)) - elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - 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) or re.match('OAI-Rel14-Docker', matchReg.group(1), re.IGNORECASE): - EPC.SetType(matchReg.group(1)) - else: - sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS or OAI-Rel14-Docker)') - elif re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCContainerPrefix=(.+)$', myArgv, re.IGNORECASE) - EPC.SetContainerPrefix(matchReg.group(1)) - elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ADBIPAddress = matchReg.group(1) - elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) - 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): - CiTestObj.ADBCentralized = False - else: - 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) - CiTestObj.ADBPassword = matchReg.group(1) - elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) - 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) - CiTestObj.UEIPAddress = matchReg.group(1) - elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UEUserName = matchReg.group(1) - elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UEPassword = matchReg.group(1) - elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) - 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')): - CiTestObj.finalStatus = True - else: - HELP.GenericHelp(CONST.Version) - sys.exit('Invalid Parameter: ' + myArgv) - if re.match('^TerminateeNB$', mode, re.IGNORECASE): - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - RAN.SeteNB_serverId('0') - RAN.SeteNB_instance('0') - RAN.SeteNBSourceCodePath('/tmp/') + RAN.eNB_serverId='0' + RAN.eNB_instance=0 + RAN.eNBSourceCodePath='/tmp/' RAN.TerminateeNB() elif re.match('^TerminateUE$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): @@ -3455,52 +3405,52 @@ elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): signal.signal(signal.SIGUSR1, receive_signal) CiTestObj.TerminateOAIUE() elif re.match('^TerminateHSS$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.TerminateHSS() elif re.match('^TerminateMME$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.TerminateMME() elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath== '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.TerminateSPGW() elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): - if (RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): + if (RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectBuild() elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') RAN.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.LogCollectHSS() elif re.match('^LogCollectMME$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.LogCollectMME() elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.LogCollectSPGW() elif re.match('^LogCollectPing$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectPing() elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectIperf() @@ -3515,7 +3465,7 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): sys.exit('Insufficient Parameter') count = 0 foundCount = 0 - while (count < HTML.GetnbTestXMLfiles()): + while (count < HTML.nbTestXMLfiles): #xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[count] xml_test_file = sys.path[0] + "/" + CiTestObj.testXMLfiles[count] if (os.path.isfile(xml_test_file)): @@ -3524,21 +3474,21 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): except: print("Error while parsing file: " + xml_test_file) xmlRoot = xmlTree.getroot() - 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')) + HTML.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + HTML.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='test-tab-' + str(count))) + HTML.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) foundCount += 1 count += 1 - if foundCount != HTML.GetnbTestXMLfiles(): - HTML.SetnbTestXMLfiles(foundCount) + if foundCount != HTML.nbTestXMLfiles: + HTML.nbTestXMLfiles=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.htmlNb_Smartphones=len(CiTestObj.UEDevices) + HTML.htmlNb_CATM_Modules=len(CiTestObj.CatMDevices) HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress) elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): logging.debug('\u001B[1m----------------------------------------\u001B[0m') @@ -3550,19 +3500,19 @@ elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): HTML.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): - 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 == '': + if RAN.eNBIPAddress == '' or RAN.ranRepository == '' or RAN.ranBranch == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '' or EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.Type == '' or EPC.SourceCodePath == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': 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()) + if EPC.IPAddress == '' or EPC.UserName == '' or EPC.Password == '' or EPC.SourceCodePath == '' or EPC.Type == '': + HELP.EPCSrvHelp(EPC.IPAddress, EPC.UserName, EPC.Password, EPC.SourceCodePath, EPC.Type) + if RAN.ranRepository == '': + HELP.GitSrvHelp(RAN.ranRepository, RAN.ranBranch, RAN.ranCommitID, RAN.ranAllowMerge, RAN.ranTargetBranch) + if RAN.eNBIPAddress == '' or RAN.eNBUserName == '' or RAN.eNBPassword == '' or RAN.eNBSourceCodePath == '': + HELP.eNBSrvHelp(RAN.eNBIPAddress, RAN.eNBUserName, RAN.eNBPassword, RAN.eNBSourceCodePath) sys.exit('Insufficient Parameter') - 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") + if (EPC.IPAddress!= '') and (EPC.IPAddress != 'none'): + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, cwd + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(EPC.IPAddress, EPC.UserName, EPC.Password, cwd + "/active_net_interfaces.awk", "/tmp") else: if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': HELP.GenericHelp(CONST.Version) @@ -3570,7 +3520,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re #read test_case_list.xml file # if no parameters for XML file, use default value - if (HTML.GetnbTestXMLfiles() != 1): + if (HTML.nbTestXMLfiles != 1): xml_test_file = cwd + "/test_case_list.xml" else: xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0] @@ -3580,9 +3530,9 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') - if (HTML.GetnbTestXMLfiles() == 1): - HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='Test-0')) + if (HTML.nbTestXMLfiles == 1): + HTML.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + HTML.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) repeatCount = xmlRoot.findtext('repeatCount',default='1') CiTestObj.repeatCounts.append(int(repeatCount)) all_tests=xmlRoot.findall('testCase') @@ -3610,7 +3560,7 @@ 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 (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): + if (EPC.IPAddress != '') and (EPC.IPAddress != 'none'): CiTestObj.CheckFlexranCtrlInstallation() EPC.SetMmeIPAddress() @@ -3635,29 +3585,29 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re HTML.CreateHtmlTabHeader() 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) + RAN.prematureExit=True + HTML.startTime=int(round(time.time() * 1000)) + while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.prematureExit: + RAN.prematureExit=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 RAN.GetprematureExit(): + if RAN.prematureExit: break for test in all_tests: - if RAN.GetprematureExit(): + if RAN.prematureExit: break id = test.get('id') if test_case_id != id: continue CiTestObj.testCase_id = id - HTML.SettestCase_id(CiTestObj.testCase_id) - EPC.SetTestCase_id(CiTestObj.testCase_id) + HTML.testCase_id=CiTestObj.testCase_id + EPC.testCase_id=CiTestObj.testCase_id CiTestObj.desc = test.findtext('desc') - HTML.Setdesc(CiTestObj.desc) + HTML.desc=CiTestObj.desc action = test.findtext('class') - if (CheckClassValidity(action, id) == False): + if (CheckClassValidity(xml_class_list, action, id) == False): continue CiTestObj.ShowTestID() GetParametersFromXML(action) @@ -3672,7 +3622,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re elif action == 'Initialize_eNB': check_eNB = False check_OAI_UE = False - RAN.SetpStatus(CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE)) + RAN.pStatus=CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE) RAN.InitializeeNB() elif action == 'Terminate_eNB': @@ -3738,16 +3688,20 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re if ldpc.exitStatus==1:sys.exit() elif action == 'Run_PhySim': HTML=ldpc.Run_PhySim(HTML,CONST,id) + elif action == 'COTS_UE_Airplane': + COTS_UE.Set_Airplane(COTS_UE.runargs) else: - sys.exit('Invalid action') + sys.exit('Invalid class (action) from xml') CiTestObj.FailReportCnt += 1 - if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): + if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.prematureExit: logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') HTML.CreateHtmlTabFooter(False) sys.exit('Failed Scenario') else: logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') HTML.CreateHtmlTabFooter(True) +elif re.match('^LoadParams$', mode, re.IGNORECASE): + pass else: HELP.GenericHelp(CONST.Version) sys.exit('Invalid mode') diff --git a/ci-scripts/py_params.yaml b/ci-scripts/py_params.yaml new file mode 100644 index 0000000000..303d5d1006 --- /dev/null +++ b/ci-scripts/py_params.yaml @@ -0,0 +1,53 @@ +eNBRepository : b +ranRepository : c +eNB_AllowMerge : +ranAllowMerge : +eNBBranch : f +ranBranch : g +eNBCommitID : +ranCommitID : i +eNBTargetBranch : j +ranTargetBranch : k + +nodes : + - type : eNB + IPAddress : 001.1.1 + UserName : toto + Password : qwe + SourceCodePath : l + - type : gNB + IPAddress : 002.2.2 + UserName : tata + Password : asd + SourceCodePath : m + - type : eNB + IPAddress : 003.3.3 + UserName : titi + Password : zxc + SourceCodePath : n + - type : gNB + IPAddress : 004.4.4 + UserName : caca + Password : pepe + SourceCodePath : o + +EPCIPAddress : p +EPCUserName : q +EPCPassword : r +EPCSourceCodePath : s +EPCType : t +EPCContainerPrefix : u + +ADBIPAddress : v +ADBUserName : w +ADBType : x +ADBPassword : y + +XMLTestFile : z + +UEIPAddress : qqq +UEUserName : www +UEPassword : eee +UESourceCodePath : yyy + +finalStatus : bbb \ No newline at end of file diff --git a/ci-scripts/py_params_template.yaml b/ci-scripts/py_params_template.yaml new file mode 100644 index 0000000000..aaf31c1576 --- /dev/null +++ b/ci-scripts/py_params_template.yaml @@ -0,0 +1,97 @@ +eNBRepository : b +ranRepository : c +eNB_AllowMerge : +ranAllowMerge : +eNBBranch : f +ranBranch : g +eNBCommitID : +ranCommitID : i +eNBTargetBranch : j +ranTargetBranch : k + + +RAN: + RAN_inst_0: + name : RAN_1 + nodes : + - type : eNB + IPAddress : 001.1.1 + UserName : toto + Password : qwe + SourceCodePath : l + - type : gNB + IPAddress : 002.2.2 + UserName : tata + Password : asd + SourceCodePath : m + - type : eNB + IPAddress : 003.3.3 + UserName : titi + Password : zxc + SourceCodePath : n + - type : gNB + IPAddress : 004.4.4 + UserName : caca + Password : pepe + SourceCodePath : o + RAN_inst_1: + name : RAN_2 + nodes : + - type : eNB + IPAddress : 101.1.1 + UserName : toto + Password : qwe + SourceCodePath : l + - type : gNB + IPAddress : 102.2.2 + UserName : zaza + Password : asd + SourceCodePath : m + - type : eNB + IPAddress : 103.3.3 + UserName : zizi + Password : zxc + SourceCodePath : n + - type : gNB + IPAddress : 104.4.4 + UserName : aaaa + Password : pepe + SourceCodePath : o + + + +EPC: + EPC_inst_0: + EPCIPAddress : p + EPCUserName : q + EPCPassword : r + EPCSourceCodePath : s + EPCType : t + EPCContainerPrefix : u + +ADB: + ADBIPAddress : v + ADBUserName : w + ADBType : x + ADBPassword : y + + +UE: + UE_inst_0: + name : UE_1 + type : + UEIPAddress : qqq + UEUserName : www + UEPassword : eee + UESourceCodePath : yyy + UE_inst_1: + name : UE_2 + type : + UEIPAddress : bloblob + UEUserName : gwou + UEPassword : zebu + UESourceCodePath : pop + + +XMLTestFile : z +finalStatus : bbb \ No newline at end of file diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 287c18021e..96f28e21fe 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -77,8 +77,8 @@ class RANManagement(): self.backgroundBuildTestId = ['', '', ''] self.Build_eNB_forced_workspace_cleanup = False self.Initialize_eNB_args = '' - self.air_interface = 'lte' - self.eNB_instance = '' + self.air_interface = ['', '', ''] #changed from 'lte' to '' may lead to side effects in main + self.eNB_instance = 0 self.eNB_serverId = '' self.eNBLogFiles = ['', '', ''] self.eNBOptions = ['', '', ''] @@ -91,140 +91,7 @@ class RANManagement(): 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 @@ -254,17 +121,23 @@ class RANManagement(): 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) + + # Check if we build an 5G-NR gNB or an LTE eNB or an OCP eNB + result = re.search('--eNBocp', self.Build_eNB_args) if result is not None: - self.air_interface = 'nr' - else: - self.air_interface = 'lte' + self.air_interface[self.eNB_instance] = 'ocp-enb' + else: + result = re.search('--gNB', self.Build_eNB_args) + if result is not None: + self.air_interface[self.eNB_instance] = 'nr-softmodem' + else: + self.air_interface[self.eNB_instance] = 'lte-softmodem' + # 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() + self.testCase_id = self.htmlObj.testCase_id else: self.testCase_id = '000000' # on RedHat/CentOS .git extension is mandatory @@ -332,7 +205,8 @@ class RANManagement(): 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.command('echo ' + lPassWord + ' | sudo -S ls', '\$', 5) + mySSH.command('echo $USER; nohup sudo -E ./my-lte-softmodem-build.sh' + ' > ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ' + ' 2>&1 &', lUserName, 5) mySSH.close() if self.htmlObj is not None: self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) @@ -378,21 +252,21 @@ class RANManagement(): def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): if self.htmlObj is not None: - self.htmlObj.SettestCase_id(testcaseId) + self.htmlObj.testCase_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()) + + #check if we have the build corresponding to the air interface keywords (nr-softmode, lte-softmodem, ocp-enb) + logging.info('CHECK Build with IP='+lIpAddr+' SourcePath='+lSourcePath) + result = re.search(self.air_interface[self.eNB_instance], mySSH.getBefore()) if result is None: - buildStatus = False + buildStatus = False #if not, build failed else: + buildStatus = True # 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) @@ -404,6 +278,8 @@ class RANManagement(): 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) @@ -420,18 +296,20 @@ class RANManagement(): 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) + #-qq quiet / -u update orcreate files + mySSH.command('unzip -u -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) mySSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) mySSH.close() else: mySSH.close() + #generate logging info depending on buildStatus and air interface if buildStatus: - logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') + logging.info('\u001B[1m Building OAI ' + self.air_interface[self.eNB_instance] + ' Pass\u001B[0m') if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + 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') + logging.error('\u001B[1m Building OAI ' + self.air_interface[self.eNB_instance] + ' Failed\u001B[0m') if self.htmlObj is not None: self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'KO', CONST.ALL_PROCESSES_OK) self.htmlObj.CreateHtmlTabFooter(False) @@ -458,22 +336,22 @@ class RANManagement(): sys.exit('Insufficient Parameter') if self.htmlObj is not None: - self.testCase_id = self.htmlObj.GettestCase_id() + self.testCase_id = self.htmlObj.testCase_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.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' ' + 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() + localEpcIpAddr = self.epcObj.IPAddress + localEpcUserName = self.epcObj.UserName + localEpcPassword = self.epcObj.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) mySSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', mySSH.getBefore()) @@ -522,12 +400,14 @@ class RANManagement(): # Make a copy and adapt to EPC / eNB IP addresses mySSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) if self.epcObj is not None: - localMmeIpAddr = self.epcObj.GetMmeIPAddress() + localMmeIpAddr = self.epcObj.MmeIPAddress mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + localMmeIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_GNB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_FR1_CTL_ENB_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); if self.flexranCtrlInstalled and self.flexranCtrlStarted: mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); else: @@ -549,15 +429,11 @@ class RANManagement(): if self.air_interface == 'nr': mySSH.command('if [ -e rbconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm rbconfig.raw; fi', '\$', 5) mySSH.command('if [ -e reconfig.raw ]; then echo ' + lPassWord + ' | sudo -S rm reconfig.raw; fi', '\$', 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) + # NOTE: WE SHALL do a check if the executable is present (in case build went wrong) + mySSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface[self.eNB_instance] + ' -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) + mySSH.command('echo $USER; nohup sudo -E ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' if extra_options != '': self.eNBOptions[int(self.eNB_instance)] = extra_options @@ -574,15 +450,15 @@ class RANManagement(): 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') + logging.error('\u001B[1;37;41m eNB/gNB/ocp-eNB logging system did not show got sync! \u001B[0m') if self.htmlObj is not None: - self.htmlObj.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) + self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if (result is not None) and (self.epcObj is not None): - localEpcIpAddr = self.epcObj.GetIPAddress() - localEpcUserName = self.epcObj.GetUserName() - localEpcPassword = self.epcObj.GetPassword() + localEpcIpAddr = self.epcObj.IPAddress + localEpcUserName = self.epcObj.UserName + localEpcPassword = self.epcObj.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) @@ -634,8 +510,8 @@ class RANManagement(): 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') + self.htmlObj.CreateHtmlTestRow(self.air_interface[self.eNB_instance] + ' -O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) + logging.debug('\u001B[1m Initialize eNB/gNB/ocp-eNB Completed\u001B[0m') def CheckeNBProcess(self, status_queue): try: @@ -658,8 +534,8 @@ class RANManagement(): 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()) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface[self.eNB_instance] + ' | grep -v grep', '\$', 5) + result = re.search(self.air_interface[self.eNB_instance], 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) @@ -691,29 +567,28 @@ class RANManagement(): mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) - if self.air_interface == 'lte': + if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): 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()) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never -e softmodem -e ocp-enb | grep -v grep', '\$', 5) + result = re.search('(-softmodem|ocp)', 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) + mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem ocp-enb || 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()) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never -e softmodem -e ocp-enb | grep -v grep', '\$', 5) + result = re.search('(-softmodem|ocp)', mySSH.getBefore()) if result is not None: - mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem ocp-enb || 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() + localEpcIpAddr = self.epcObj.IPAddress + localEpcUserName = self.epcObj.UserName + localEpcPassword = self.epcObj.Password mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) @@ -752,7 +627,7 @@ class RANManagement(): 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.htmleNBFailureMsg='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 @@ -823,7 +698,30 @@ class RANManagement(): X2HO_inNbProcedures = 0 X2HO_outNbProcedures = 0 global_status = CONST.ALL_PROCESSES_OK + # Runtime statistics + runTime = '' + userTime = '' + systemTime = '' + maxPhyMemUsage = '' + nbContextSwitches = '' for line in enb_log_file.readlines(): + # Runtime statistics + result = re.search('Run time:' ,str(line)) + if result is not None: + runTime = str(line).strip() + if runTime != '': + result = re.search('Time executing user inst', str(line)) + if result is not None: + userTime = 'to be decoded - 1' + result = re.search('Time executing system inst', str(line)) + if result is not None: + systemTime = 'to be decoded - 2' + result = re.search('Max. Phy. memory usage:', str(line)) + if result is not None: + maxPhyMemUsage = 'to be decoded - 3' + result = re.search('Number of context switch.*process origin', str(line)) + if result is not None: + nbContextSwitches = 'to be decoded - 4' 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: @@ -896,8 +794,7 @@ class RANManagement(): if result is not None: rrcSetupComplete += 1 result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) - if result is not None: - rrcReleaseRequest += 1 + if result is not None: rrcReleaseRequest += 1 result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) if result is not None: rrcReconfigRequest += 1 @@ -955,11 +852,11 @@ class RANManagement(): mbmsRequestMsg += 1 enb_log_file.close() logging.debug(' File analysis completed') - if self.air_interface == 'lte': + if (self.air_interface[self.eNB_instance] == 'lte-softmodem') or (self.air_interface[self.eNB_instance] == 'ocp-enb'): nodeB_prefix = 'e' else: nodeB_prefix = 'g' - if self.air_interface == 'nr': + if self.air_interface[self.eNB_instance] == 'nr-softmodem': if ulschReceiveOK > 0: statMsg = nodeB_prefix + 'NB showed ' + str(ulschReceiveOK) + ' "ULSCH received ok" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') @@ -1080,5 +977,12 @@ class RANManagement(): htmleNBFailureMsg += rlcMsg + '\n' global_status = CONST.ENB_PROCESS_REALTIME_ISSUE if self.htmlObj is not None: - self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) + self.htmlObj.htmleNBFailureMsg=htmleNBFailureMsg + # Runtime statistics + if runTime != '': + logging.debug(runTime) + logging.debug('Time executing user inst : ' + userTime) + logging.debug('Time executing system inst : ' + systemTime) + logging.debug('Max Physical Memory Usage : ' + maxPhyMemUsage) + logging.debug('Nb Context Switches : ' + nbContextSwitches) return global_status diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index ba0f900f29..ed0cf5379a 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -101,6 +101,18 @@ class SSHConnection(): else: sys.exit('SSH Connection Failed') + + + + def cde_check_value(self, commandline, expected, timeout): + logging.debug(commandline) + self.ssh.timeout = timeout + self.ssh.sendline(commandline) + expected.append(pexpect.EOF) + expected.append(pexpect.TIMEOUT) + self.sshresponse = self.ssh.expect(expected) + return self.sshresponse + def command(self, commandline, expectedline, timeout): logging.debug(commandline) self.ssh.timeout = timeout diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml new file mode 100755 index 0000000000..e80063a120 --- /dev/null +++ b/ci-scripts/xml_class_list.yml @@ -0,0 +1,35 @@ + - COTS_UE_Airplane + - Build_PhySim + - Run_PhySim + - Build_eNB + - WaitEndBuild_eNB + - Initialize_eNB + - Terminate_eNB + - Initialize_UE + - Terminate_UE + - Attach_UE + - Detach_UE + - Build_OAI_UE + - Initialize_OAI_UE + - Terminate_OAI_UE + - DataDisable_UE + - DataEnable_UE + - CheckStatusUE + - Ping + - Iperf + - Reboot_UE + - Initialize_FlexranCtrl + - Terminate_FlexranCtrl + - Initialize_HSS + - Terminate_HSS + - Initialize_MME + - Terminate_MME + - Initialize_SPGW + - Terminate_SPGW + - Initialize_CatM_module + - Terminate_CatM_module + - Attach_CatM_module + - Detach_CatM_module + - Ping_CatM_module + - IdleSleep + - Perform_X2_Handover diff --git a/ci-scripts/xml_files/enb_ocp_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/enb_ocp_usrp210_band7_test_05mhz_tm1.xml new file mode 100644 index 0000000000..a4caa77075 --- /dev/null +++ b/ci-scripts/xml_files/enb_ocp_usrp210_band7_test_05mhz_tm1.xml @@ -0,0 +1,147 @@ + + + test-05-tm1 + Test-05MHz-TM1 + tasks + 4 + + 030201 + 040101 + 030101 040301 040501 040603 040604 040605 040606 040607 040641 040642 040643 040644 040401 040201 030201 + + + + + Initialize_eNB + Initialize OCP-eNB (FDD/Band7/5MHz) + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf + ocp + + + + Terminate_eNB + Terminate OCP-eNB + ocp + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(balanced profile) + -u -b 15M -t 30 -i 1 + 50 + balanced + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(single-ue profile) + -u -b 15M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec)(unbalanced profile) + -u -b 15M -t 30 -i 1 + 50 + unbalanced + + + + Iperf + iperf (5MHz - DL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm + 50 + balanced + + + + Iperf + iperf (5MHz - UL/9Mbps/UDP)(30 sec)(balanced profile) + -u -b 9M -t 30 -i 1 -R + 50 + balanced + + + + Iperf + iperf (5MHz - UL/9Mbps/UDP)(30 sec)(single-ue profile) + -u -b 9M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/TCP)(30 sec)(single-ue profile) + -t 30 -i 1 -fm -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/TCP)(30 sec)(balanced profile) + -t 30 -i 1 -fm -R + 50 + balanced + + + diff --git a/ci-scripts/xml_files/enb_ocp_usrp210_build.xml b/ci-scripts/xml_files/enb_ocp_usrp210_build.xml new file mode 100644 index 0000000000..33a0fc205e --- /dev/null +++ b/ci-scripts/xml_files/enb_ocp_usrp210_build.xml @@ -0,0 +1,38 @@ + + + build-tab + Build + wrench + + 010101 + + + + + Build_eNB + Build eNB OCP (USRP) + -w USRP -c --eNBocp --ninja + + + diff --git a/ci-scripts/xml_files/fr1_multi_node_build.xml b/ci-scripts/xml_files/fr1_multi_node_build.xml new file mode 100644 index 0000000000..7b4eacef3a --- /dev/null +++ b/ci-scripts/xml_files/fr1_multi_node_build.xml @@ -0,0 +1,66 @@ + + + build-tab + Build + wrench + + 000001 000002 + 000003 000004 + + + + + Build_eNB + Build eNB + -w USRP -c --eNB --ninja + 0 + 0 + True + + + + WaitEndBuild_eNB + Wait for end of Build eNB + 0 + 0 + + + + Build_eNB + Build gNB + -w USRP -c --gNB --ninja + 1 + 1 + True + + + + WaitEndBuild_eNB + Wait for end of Build gNB + 1 + 1 + + + + diff --git a/ci-scripts/xml_files/fr1_multi_node_terminate.xml b/ci-scripts/xml_files/fr1_multi_node_terminate.xml new file mode 100644 index 0000000000..cbaaf8ba99 --- /dev/null +++ b/ci-scripts/xml_files/fr1_multi_node_terminate.xml @@ -0,0 +1,50 @@ + + + test-fr1-tm1 + Test-FR1-TM1 + tasks + 1 + + 070001 + 070000 + + + + + + Terminate_eNB + Terminate eNB + 0 + 0 + + + + Terminate_eNB + Terminate gNB + 1 + 1 + + + + diff --git a/ci-scripts/xml_files/fr1_multi_node_test.xml b/ci-scripts/xml_files/fr1_multi_node_test.xml new file mode 100644 index 0000000000..8c56f0bcec --- /dev/null +++ b/ci-scripts/xml_files/fr1_multi_node_test.xml @@ -0,0 +1,77 @@ + + + test-fr1-tm1 + Test-FR1-TM1 + tasks + 1 + + 030000 + 040000 + 000001 + 070001 + 070000 + + + + + + Initialize_eNB + Initialize eNB + -O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf + 0 + 0 + lte + + + + Initialize_eNB + Initialize gNB (3/4 sampling rate) + -O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E + 1 + 1 + nr + + + + IdleSleep + Sleep + 30 + + + + Terminate_eNB + Terminate eNB + 0 + 0 + + + + Terminate_eNB + Terminate gNB + 1 + 1 + + + + diff --git a/ci-scripts/xml_files/fr1_toggle_cots_ue.xml b/ci-scripts/xml_files/fr1_toggle_cots_ue.xml new file mode 100644 index 0000000000..b2267efc77 --- /dev/null +++ b/ci-scripts/xml_files/fr1_toggle_cots_ue.xml @@ -0,0 +1,39 @@ + + + test-airplane-mode + AirplaneToggle + tasks + + 010000 + + + + + COTS_UE_Airplane + Toggle COTS Airplane mode ON + ON + + + + diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml index 97d6ef06f6..e2662180c5 100644 --- a/ci-scripts/xml_files/gnb_usrp_build.xml +++ b/ci-scripts/xml_files/gnb_usrp_build.xml @@ -34,7 +34,7 @@ TesteNB Build_eNB Build gNB (USRP) - --gNB -w USRP + --gNB -w USRP --ninja True diff --git a/ci-scripts/xml_files/nr_ue_usrp_build.xml b/ci-scripts/xml_files/nr_ue_usrp_build.xml index c3c842b85a..bc04efdb4b 100644 --- a/ci-scripts/xml_files/nr_ue_usrp_build.xml +++ b/ci-scripts/xml_files/nr_ue_usrp_build.xml @@ -34,7 +34,7 @@ TestUE Build_OAI_UE Build NR UE (USRP) - --nrUE -w USRP + --nrUE -w USRP --ninja false diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 67d4b03940..050d50f9f5 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -27,6 +27,10 @@ cmake_minimum_required (VERSION 3.0) # Base directories, compatible with legacy OAI building # ######################################################### set (OPENAIR_DIR $ENV{OPENAIR_DIR}) +if("${OPENAIR_DIR}" STREQUAL "") + string(REGEX REPLACE "/cmake_targets.*$" "" OPENAIR_DIR ${CMAKE_CURRENT_BINARY_DIR}) +endif() + set (NFAPI_DIR ${OPENAIR_DIR}/nfapi/open-nFAPI) set (NFAPI_USER_DIR ${OPENAIR_DIR}/nfapi/oai_integration) set (OPENAIR1_DIR ${OPENAIR_DIR}/openair1) @@ -1252,7 +1256,7 @@ set(SCHED_SRC_NR_UE ${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c ${OPENAIR1_DIR}/SCHED_NR_UE/fapi_nr_ue_l1.c - ${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c + ${OPENAIR1_DIR}/SCHED_NR_UE/phy_frame_config_nr_ue.c ${OPENAIR1_DIR}/SCHED_NR_UE/harq_nr.c ${OPENAIR1_DIR}/SCHED_NR_UE/pucch_uci_ue_nr.c ${OPENAIR1_DIR}/SCHED_NR_UE/pucch_power_control_ue_nr.c @@ -1830,6 +1834,7 @@ set (MAC_SRC ${MAC_DIR}/eNB_scheduler_fairRR.c ${MAC_DIR}/eNB_scheduler_phytest.c ${MAC_DIR}/pre_processor.c + ${MAC_DIR}/slicing/slicing.c ${MAC_DIR}/config.c ${MAC_DIR}/config_ue.c ) @@ -2473,8 +2478,8 @@ add_library(uescope MODULE ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} ${XFORMS_ target_link_libraries(enbscope ${XFORMS_LIBRARIES}) target_link_libraries(uescope ${XFORMS_LIBRARIES}) -add_library(gnbscope MODULE ${XFORMS_SOURCE_NR}) -target_link_libraries(gnbscope ${XFORMS_LIBRARIES}) +add_library(nrscope MODULE ${XFORMS_SOURCE_NR}) +target_link_libraries(nrscope ${XFORMS_LIBRARIES}) add_library(rfsimulator MODULE @@ -2623,7 +2628,7 @@ add_executable(ocp-enb ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} ) -add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer) +add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer coding params_libconfig rfsimulator) target_link_libraries (ocp-enb -Wl,--start-group @@ -2730,7 +2735,7 @@ add_executable(nr-softmodem ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${GTPU_need_ITTI} - ${XFORMS_SOURCE_NR} + ${XFORMSINTERFACE_SOURCE} ${T_SOURCE} ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} @@ -2772,7 +2777,7 @@ add_executable(nr-uesoftmodem ${OPENAIR_DIR}/common/utils/utils.c ${OPENAIR_DIR}/common/utils/system.c ${OPENAIR_DIR}/common/utils/nr/nr_common.c - ${XFORMS_SOURCE_NR} + ${XFORMSINTERFACE_SOURCE} ${T_SOURCE} ${UTIL_SRC} ${CONFIG_SOURCES} diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 88b8811575..36af9eaee4 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -67,7 +67,7 @@ UE_TIMING_TRACE="False" USRP_REC_PLAY="False" BUILD_ECLIPSE=0 NR="False" -OPTIONAL_LIBRARIES="telnetsrv enbscope uescope msc" +OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope msc" trap handle_ctrl_c INT function print_help() { @@ -96,7 +96,9 @@ Options enable cmake debugging messages --eNB Makes the LTE softmodem ---gNB +--eNBocp + Makes the OCP LTE softmodem +-gNB Makes the NR softmodem --nrUE Makes the NR UE softmodem @@ -237,7 +239,11 @@ function main() { eNB=1 echo_info "Will compile eNB" shift;; - --gNB) + --eNBocp) + eNBocp=1 + echo_info "Will compile OCP eNB" + shift;; + --gNB) gNB=1 NR="True" echo_info "Will compile gNB" @@ -443,7 +449,7 @@ function main() { ######################################################## # to be discussed - if [ "$eNB" = "1" -o "$gNB" = "1" ] ; then + if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$gNB" = "1" ] ; then if [ "$HW" = "None" -a "$TP" = "None" ] ; then echo_info "No local radio head and no transport protocol selected" fi @@ -574,12 +580,13 @@ function main() { config_libconfig_shlib=params_libconfig # first generate the CMakefile in the right directory - if [ "$eNB" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HW" = "EXMIMO" ] ; then + if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HW" = "EXMIMO" ] ; then # softmodem compilation cmake_file=$DIR/$build_dir/CMakeLists.txt echo "cmake_minimum_required(VERSION 2.8)" > $cmake_file + echo "project (OpenAirInterface)" >> $cmake_file echo "set ( CMAKE_BUILD_TYPE $CMAKE_BUILD_TYPE )" >> $cmake_file echo "set ( CFLAGS_PROCESSOR_USER \"$CFLAGS_PROCESSOR_USER\" )" >> $cmake_file echo "set ( UE_EXPANSION $UE_EXPANSION )" >> $cmake_file @@ -606,6 +613,9 @@ function main() { if [ "$eNB" = "1" ] ; then execlist="$execlist lte-softmodem" fi + if [ "$eNBocp" = "1" ] ; then + execlist="$execlist ocp-enb" + fi if [ "$gNB" = "1" ] ; then execlist="$execlist nr-softmodem" fi @@ -821,7 +831,7 @@ function main() { #################################################### # Build RF device and transport protocol libraries # #################################################### - if [ "$eNB" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HWLAT" = "1" ] ; then + if [ "$eNB" = "1" -o "$eNBocp" = "1" -o "$UE" = "1" -o "$gNB" = "1" -o "$nrUE" = "1" -o "$HWLAT" = "1" ] ; then # build RF device libraries if [ "$HW" != "None" ] ; then diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index 22933fdd5b..1680410ebb 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -80,7 +80,7 @@ task_list_t tasks[TASK_MAX]; void *itti_malloc(task_id_t origin_task_id, task_id_t destination_task_id, ssize_t size) { void *ptr = NULL; - AssertFatal ((ptr=malloc (size)) != NULL, "Memory allocation of %zu bytes failed (%d -> %d)!\n", + AssertFatal ((ptr=calloc (size, 1)) != NULL, "Memory allocation of %zu bytes failed (%d -> %d)!\n", size, origin_task_id, destination_task_id); return ptr; } diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index 06a5d350c7..03f7af99bc 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -53,6 +53,7 @@ #include #include "common/utils/load_module_shlib.h" #include "common/config/config_userapi.h" +#include "common/utils/threadPool/thread-pool.h" #include "executables/softmodem-common.h" #include @@ -507,12 +508,22 @@ int process_command(char *buf) { } rt= CMDSTATUS_FOUND; - } else if (strncasecmp(cmd,"get",3) == 0 || strncasecmp(cmd,"set",3) == 0) { + } else if (strcasecmp(cmd,"get") == 0 || strcasecmp(cmd,"set") == 0) { rt= setgetvar(i,cmd[0],cmdb); } else { for (k=0 ; telnetparams.CmdParsers[i].cmd[k].cmdfunc != NULL ; k++) { if (strncasecmp(cmd, telnetparams.CmdParsers[i].cmd[k].cmdname,sizeof(telnetparams.CmdParsers[i].cmd[k].cmdname)) == 0) { - telnetparams.CmdParsers[i].cmd[k].cmdfunc(cmdb, telnetparams.telnetdbg, client_printf); + if (telnetparams.CmdParsers[i].cmd[k].qptr != NULL) { + notifiedFIFO_elt_t *msg =newNotifiedFIFO_elt(sizeof(telnetsrv_qmsg_t),0,NULL,NULL); + telnetsrv_qmsg_t *cmddata=NotifiedFifoData(msg); + cmddata->cmdfunc=(qcmdfunc_t)telnetparams.CmdParsers[i].cmd[k].cmdfunc; + cmddata->prnt=client_printf; + cmddata->debug=telnetparams.telnetdbg; + cmddata->cmdbuff=strdup(cmdb); + pushNotifiedFIFO(telnetparams.CmdParsers[i].cmd[k].qptr, msg); + } else { + telnetparams.CmdParsers[i].cmd[k].cmdfunc(cmdb, telnetparams.telnetdbg, client_printf); + } rt= CMDSTATUS_FOUND; } } /* for k */ @@ -673,6 +684,16 @@ void run_telnetsrv(void) { return; } +void poll_telnetcmdq(void *qid, void *arg) { + notifiedFIFO_elt_t *msg = pollNotifiedFIFO((notifiedFIFO_t *)qid); + + if (msg != NULL) { + telnetsrv_qmsg_t *msgdata=NotifiedFifoData(msg); + msgdata->cmdfunc(msgdata->cmdbuff,msgdata->debug,msgdata->prnt,arg); + free(msgdata->cmdbuff); + delNotifiedFIFO_elt(msg); + } +} /*------------------------------------------------------------------------------------------------*/ /* load the commands delivered with the telnet server * @@ -758,6 +779,7 @@ int telnetsrv_autoinit(void) { */ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd) { int i; + notifiedFIFO_t *afifo=NULL; if( modulename == NULL || var == NULL || cmd == NULL) { fprintf(stderr,"[TELNETSRV] Telnet server, add_telnetcmd: invalid parameters\n"); @@ -769,6 +791,13 @@ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmdde strncpy(telnetparams.CmdParsers[i].module,modulename,sizeof(telnetparams.CmdParsers[i].module)-1); telnetparams.CmdParsers[i].cmd = cmd; telnetparams.CmdParsers[i].var = var; + if (cmd->cmdflags & TELNETSRV_CMDFLAG_PUSHINTPOOLQ) { + if (afifo == NULL) { + afifo = malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(afifo); + } + cmd->qptr = afifo; + } printf("[TELNETSRV] Telnet server: module %i = %s added to shell\n", i,telnetparams.CmdParsers[i].module); break; @@ -797,8 +826,10 @@ int telnetsrv_checkbuildver(char *mainexec_buildversion, char **shlib_buildvers } int telnetsrv_getfarray(loader_shlibfunc_t **farray) { - *farray=malloc(sizeof(loader_shlibfunc_t)); + *farray=malloc(sizeof(loader_shlibfunc_t)*2); (*farray)[0].fname=TELNET_ADDCMD_FNAME; (*farray)[0].fptr=(int (*)(void) )add_telnetcmd; - return 1; + (*farray)[1].fname=TELNET_POLLCMDQ_FNAME; + (*farray)[1].fptr=(int (*)(void) )poll_telnetcmdq; + return ( 2); } diff --git a/common/utils/telnetsrv/telnetsrv.h b/common/utils/telnetsrv/telnetsrv.h index debb9f02ec..b66641d5c8 100644 --- a/common/utils/telnetsrv/telnetsrv.h +++ b/common/utils/telnetsrv/telnetsrv.h @@ -53,13 +53,26 @@ /* to add a set of new command to the telnet server shell */ typedef void(*telnet_printfunc_t)(const char* format, ...); typedef int(*cmdfunc_t)(char*, int, telnet_printfunc_t prnt); +typedef int(*qcmdfunc_t)(char*, int, telnet_printfunc_t prnt,void *arg); +#define TELNETSRV_CMDFLAG_PUSHINTPOOLQ (1<<0) // ask the telnet server to push the command in a thread pool queue typedef struct cmddef { char cmdname[TELNET_CMD_MAXSIZE]; char helpstr[TELNET_HELPSTR_SIZE]; cmdfunc_t cmdfunc; + unsigned int cmdflags; + void *qptr; } telnetshell_cmddef_t; +/*----------------------------------------------------------------------------*/ +/* structure used to send a command via a message queue to enable */ +/* executing a command in a thread different from the telnet server thread */ +typedef struct telnetsrv_qmsg { + qcmdfunc_t cmdfunc; + telnet_printfunc_t prnt; + int debug; + char *cmdbuff; +} telnetsrv_qmsg_t; /*----------------------------------------------------------------------------*/ /*structure to be used when adding a module to the telnet server */ /* This is the first parameter of the add_telnetcmd function, which can be used */ @@ -111,9 +124,6 @@ typedef struct { } telnetsrv_params_t; - -typedef int(*addcmdfunc_t)(char*, telnetshell_vardef_t*, telnetshell_cmddef_t*); - typedef void(*settelnetmodule_t)(char *name, void *ptr); /*-------------------------------------------------------------------------------------------*/ @@ -133,7 +143,9 @@ VT escape sequence definition, for smarter display.... /*---------------------------------------------------------------------------------------------*/ #define TELNET_ADDCMD_FNAME "add_telnetcmd" +#define TELNET_POLLCMDQ_FNAME "poll_telnetcmdq" typedef int(*add_telnetcmd_func_t)(char *, telnetshell_vardef_t *, telnetshell_cmddef_t *); +typedef void(*poll_telnetcmdq_func_t)(void *qid,void *arg); #ifdef TELNETSERVERCODE int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd); void set_sched(pthread_t tid, int pid,int priority); diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index cbb2dbe3d9..e1446f15d7 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -111,9 +111,10 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { pool->activated=true; initNotifiedFIFO(&pool->incomingFifo); char *saveptr, * curptr; + char *parms_cpy=strdup(params); pool->nbThreads=0; pool->restrictRNTI=false; - curptr=strtok_r(params,",",&saveptr); + curptr=strtok_r(parms_cpy,",",&saveptr); struct one_thread * ptr; while ( curptr!=NULL ) { int c=toupper(curptr[0]); @@ -145,7 +146,7 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { curptr=strtok_r(NULL,",",&saveptr); } - + free(parms_cpy); if (pool->activated && pool->nbThreads==0) { printf("No servers created in the thread pool, exit\n"); exit(1); diff --git a/doc/TESTING_GNB_W_COTS_UE.md b/doc/TESTING_GNB_W_COTS_UE.md index e507050239..a16b4dbe13 100644 --- a/doc/TESTING_GNB_W_COTS_UE.md +++ b/doc/TESTING_GNB_W_COTS_UE.md @@ -1,4 +1,5 @@ -STATUS 2020/06/26 : information is up to date, but under continuous improvement +STATUS 2020/07/30 : under continuous improvement ; updated the configuration files links with CI approved reference files + ## Table of Contents ## @@ -78,17 +79,17 @@ https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master-documentation/do Each component (EPC, eNB, gNB) has its own configuration file. These config files are passed as arguments of the run command line, using the option -O \ -Some config examples can be found in the following folder: -https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/develop/targets/PROJECTS/GENERIC-LTE-EPC/CONF - -Also base config files can be found here: -[enb conf file](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/rh_doc_update_3/doc/testing_gnb_w_cots_ue_resources/enb.conf) -[gnb conf file](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/rh_doc_update_3/doc/testing_gnb_w_cots_ue_resources/gnb.conf) - -TO DO : attach base confif files +The **REFERENCE** files for eNB and gNB, **used by the CI**, can be found here: +[enb conf file](../ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf) +[gnb conf file](../ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf) These files have to be updated manually to set the IP addresses and frequency. + +**ATTENTION** : an **EXTERNAL** clock is used to sync the eNB and gNB, +whether the clock is internal or external is defined in the configuration files (!! details needed !!) + + 1- In the **eNB configuration file** : - look for MME IP address, and update the **ipv4 field** with the IP address of the **EPC** server ``` @@ -128,7 +129,7 @@ These files have to be updated manually to set the IP addresses and frequency. } ); ``` -- look for X2 IP address, and update the **4 fields** with the IP address of the **eNB** server (notice : even if -in principle- S1 MME is not required for gNB setting) +- look for X2 IP address, and update the **4 fields** with the IP address of the **eNB** server / **gNB** server as below (notice : even if -in principle- S1 MME is not required for gNB setting) ``` ///X2 @@ -146,11 +147,11 @@ These files have to be updated manually to set the IP addresses and frequency. { GNB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1_MME = "**YOUR_ENB_IP_ADDR**"; + GNB_IPV4_ADDRESS_FOR_S1_MME = "**YOUR_GNB_IP_ADDR**"; GNB_INTERFACE_NAME_FOR_S1U = "eth0"; - GNB_IPV4_ADDRESS_FOR_S1U = "**YOUR_ENB_IP_ADDR**"; + GNB_IPV4_ADDRESS_FOR_S1U = "**YOUR_GNB_IP_ADDR**"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 - GNB_IPV4_ADDRESS_FOR_X2C = "**YOUR_ENB_IP_ADDR**"; + GNB_IPV4_ADDRESS_FOR_X2C = "**YOUR_GNB_IP_ADDR**"; GNB_PORT_FOR_X2C = 36422; # Spec 36422 }; @@ -215,26 +216,20 @@ Execute: ``` -For example: -``` -~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf | tee mylogfile.log -``` - - - **gNB** (on the gNB host) Execute: ``` -~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O **YOUR_GNB_CONF_FILE** | tee **YOUR_LOG_FILE** +~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O **YOUR_GNB_CONF_FILE** -E | tee **YOUR_LOG_FILE** ``` -For example: -``` -~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf | tee mylogfile.log -``` +**ATTENTION** : for the gNB execution, +The -E option is required to enable the tri-quarter sampling rate when using a B2xx serie USRP +The -E opton is not needed when using a a N300 USRP + ## Test Case diff --git a/executables/main-fs6.c b/executables/main-fs6.c index ffa44bd978..d2d64d0959 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -401,7 +401,7 @@ void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_ 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)->ta=lte_est_timing_advance_pusch(&eNB->frame_parms, eNB->pusch_vars[UE_id]->drs_ch_estimates_time); 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)); diff --git a/executables/main-ocp.c b/executables/main-ocp.c index e4e42b4f23..cd221b155a 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -1123,9 +1123,6 @@ int restart_L1L2(module_id_t enb_id) { 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); @@ -1167,6 +1164,7 @@ int main ( int argc, char **argv ) { T_Config_Init(); #endif configure_linux(); + set_softmodem_sighandler(); cpuf=get_cpu_freq_GHz(); set_taus_seed (0); @@ -1347,7 +1345,7 @@ int main ( int argc, char **argv ) { // end of CI modifications //getchar(); if(IS_SOFTMODEM_DOFORMS) - load_softscope("enb"); + load_softscope("enb", NULL); itti_wait_tasks_end(); oai_exit=1; diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index bf77125975..ab10313c1a 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -75,7 +75,7 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "system.h" #include - +#include "PHY/TOOLS/phy_scope_interface.h" #include "PHY/TOOLS/nr_phy_scope.h" #include "stats.h" #include "nr-softmodem.h" @@ -156,7 +156,6 @@ char channels[128] = "0"; int rx_input_level_dBm; -uint32_t do_forms=0; int otg_enabled; //int number_of_cards = 1; @@ -454,7 +453,11 @@ static void get_options(void) { paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ; + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + get_common_options(SOFTMODEM_GNB_BIT ); config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); + CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); + @@ -723,9 +726,6 @@ int restart_L1L2(module_id_t gnb_id) { 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 gNB */ - 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"); // No more rrc thread, as many race conditions are hidden behind @@ -817,7 +817,6 @@ int main( int argc, char **argv ) configure_linux(); printf("Reading in command-line options\n"); get_options (); - get_common_options(SOFTMODEM_GNB_BIT ); if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) { fprintf(stderr,"Getting configuration failed\n"); @@ -959,14 +958,14 @@ if(!IS_SOFTMODEM_NOS1) printf("RC.nb_RU:%d\n", RC.nb_RU); // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration) printf("ALL RUs ready - init gNBs\n"); - - if (do_forms==1) { + if(IS_SOFTMODEM_DOFORMS) { + scopeParms_t p; p.argc=&argc; p.argv=argv; p.gNB=RC.gNB[0]; p.ru=RC.ru[0]; - gNBinitScope(&p); + load_softscope("nr",&p); } if (nfapi_mode != 1 && nfapi_mode != 2) { diff --git a/executables/nr-softmodem.h b/executables/nr-softmodem.h index d113ae45aa..d6cfe6b906 100644 --- a/executables/nr-softmodem.h +++ b/executables/nr-softmodem.h @@ -19,21 +19,12 @@ /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_PARAMS_DESC_GNB { \ {"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \ - {"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&wait_for_sync, defintval:0, TYPE_INT, 0}, \ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:DEFAULT_DLF, TYPE_UINT64, 0}, \ - {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ - {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, i8ptr:&threequarter_fs, defintval:0, TYPE_INT8, 0}, \ {"K" , CONFIG_HLP_ITTIL, PARAMFLAG_NOFREE, strptr:&itti_dump_file, defstrval:"/tmp/itti.dump", TYPE_STRING, 0}, \ {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ - {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ - {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \ - {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \ - {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ - {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ {"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \ {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ } diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 2f99027b75..cdcd014caa 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -35,9 +35,7 @@ #include "NR_MAC_UE/mac_proto.h" #include "RRC/NR_UE/rrc_proto.h" -//#ifndef NO_RAT_NR -#include "SCHED_NR/phy_frame_config_nr.h" -//#endif +#include "SCHED_NR_UE/phy_frame_config_nr.h" #include "SCHED_NR_UE/defs.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" @@ -577,12 +575,6 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { int computeSamplesShift(PHY_VARS_NR_UE *UE) { - if (IS_SOFTMODEM_RFSIM) { - LOG_D(PHY,"SET rx_offset %d \n",UE->rx_offset); - //UE->rx_offset_diff=0; - return 0; - } - // compute TO compensation that should be applied for this frame if ( UE->rx_offset < UE->frame_parms.samples_per_frame/2 && UE->rx_offset > 0 ) { diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 6d3bbc9038..fa816b506c 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -76,12 +76,12 @@ unsigned short config_frames[4] = {2,9,11,13}; #include #include +/* Callbacks, globals and object handlers */ + //#include "stats.h" // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) +#include "PHY/TOOLS/phy_scope_interface.h" #include "PHY/TOOLS/nr_phy_scope.h" -// at eNB 0, an UL scope for every UE -//FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - #include #include "executables/softmodem-common.h" #include "executables/thread-common.h" @@ -151,14 +151,11 @@ char ref[128] = "internal"; char channels[128] = "0"; -static char *parallel_config = NULL; -static char *worker_config = NULL; - int rx_input_level_dBm; //static int online_log_messages=0; -uint32_t do_forms=0; + int otg_enabled; //int number_of_cards = 1; @@ -761,8 +758,10 @@ int main( int argc, char **argv ) { memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs); configure_linux(); mlockall(MCL_CURRENT | MCL_FUTURE); - if (do_forms) - nrUEinitScope(PHY_vars_UE_g[0][0]); + + if(IS_SOFTMODEM_DOFORMS) { + load_softscope("nr",PHY_vars_UE_g[0][0]); + } number_of_cards = 1; for(int CC_id=0; CC_id #include #include +#include #define CU_PORT "7878" #define DU_PORT "8787" @@ -325,5 +326,6 @@ 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); +void softmodem_printresources(int sig, telnet_printfunc_t pf); extern uint16_t sf_ahead; #endif diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index e342ab0b67..f84917f12e 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -364,7 +364,7 @@ typedef struct //table 3-22 typedef struct { - nfapi_uint8_tlv_t phy_cell_id;//Physical Cell ID, 𝑁_{𝐼𝐷}^{𝑐𝑒𝑙𝑙} [38.211, sec 7.4.2.1] Value: 0 ->1007 + nfapi_uint16_tlv_t phy_cell_id;//Physical Cell ID, 𝑁_{𝐼𝐷}^{𝑐𝑒𝑙𝑙} [38.211, sec 7.4.2.1] Value: 0 ->1007 nfapi_uint8_tlv_t frame_duplex_type;//Frame duplex type Value: 0 = FDD 1 = TDD } nfapi_nr_cell_config_t; diff --git a/openair1/PHY/INIT/lte_init_ru.c b/openair1/PHY/INIT/lte_init_ru.c index dddd6b1bd5..baea52083f 100644 --- a/openair1/PHY/INIT/lte_init_ru.c +++ b/openair1/PHY/INIT/lte_init_ru.c @@ -186,7 +186,6 @@ void phy_free_RU(RU_t *ru) { int i,j,p; RU_CALIBRATION *calibration = &ru->calibration; LOG_I(PHY, "Feeing RU signal buffers (if_south %s) nb_tx %d\n", ru_if_types[ru->if_south], ru->nb_tx); - free_and_zero(ru->frame_parms); if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so free memory for time-domain signals for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdata[i]); diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 8b70b523a5..28b13112ce 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -121,9 +121,9 @@ int nr_phy_init_RU(RU_t *ru) { LOG_E(PHY,"[INIT] %s() RC.nb_nr_L1_inst:%d \n", __FUNCTION__, RC.nb_nr_L1_inst); int beam_count = 0; - if (ru->nb_log_antennas>1) { + if (ru->nb_tx>1) {//Enable beamforming when nb_tx > 1 for (p=0;pnb_log_antennas;p++) { - if ((fp->L_ssb >> p) & 0x01) + if ((fp->L_ssb >> (63-p)) & 0x01)//64 bit-map with the MSB @2⁶³ corresponds to SSB ssb_index 0 beam_count++; } AssertFatal(ru->nb_bfw==(beam_count*ru->nb_tx),"Number of beam weights from config file is %d while the expected number is %d",ru->nb_bfw,(beam_count*ru->nb_tx)); @@ -131,7 +131,7 @@ int nr_phy_init_RU(RU_t *ru) { int l_ind = 0; for (i=0; inb_log_antennas;p++) { - if ((fp->L_ssb >> p) & 0x01) { + if ((fp->L_ssb >> (63-p)) & 0x01) { ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*)); for (j=0; jnb_tx; j++) { ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t)); diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index c3fe9c54b1..6045930b17 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -308,7 +308,7 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, int num_tx_ant = (cfg == NULL) ? fp->Lmax : cfg->carrier_config.num_tx_ant.value; for (int p=0; pN_ssb += ((fp->L_ssb >> p) & 0x01); + fp->N_ssb += ((fp->L_ssb >> (63-p)) & 0x01); return 0; @@ -389,7 +389,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->N_ssb = 0; for (int p=0; pLmax; p++) - fp->N_ssb += ((fp->L_ssb >> p) & 0x01); + fp->N_ssb += ((fp->L_ssb >> (63-p)) & 0x01); return 0; } diff --git a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c index e4083863f0..ab7c2b9091 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c @@ -55,7 +55,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 uint8_t preamble_index = ue->prach_resources[eNB_id]->ra_PreambleIndex; uint8_t tdd_mapindex = ue->prach_resources[eNB_id]->ra_TDD_map_index; int16_t *prachF = ue->prach_vars[eNB_id]->prachF; - static int16_t prach_tmp[45600*2] __attribute__((aligned(32))); + static int16_t prach_tmp[45600*4] __attribute__((aligned(32))); int16_t *prach = prach_tmp; int16_t *prach2; int16_t amp = ue->prach_vars[eNB_id]->amp; diff --git a/openair1/PHY/MODULATION/beamforming.c b/openair1/PHY/MODULATION/beamforming.c index 79e220ac37..b1f419b172 100644 --- a/openair1/PHY/MODULATION/beamforming.c +++ b/openair1/PHY/MODULATION/beamforming.c @@ -155,7 +155,7 @@ int nr_beam_precoding(int32_t **txdataF, memset(&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size],0,sizeof(int32_t)*(frame_parms->ofdm_symbol_size)); for (p=0; pL_ssb >> p) & 0x01) { + if ((frame_parms->L_ssb >> (63-p)) & 0x01) { multadd_cpx_vector((int16_t*)&txdataF[p][symbol*frame_parms->ofdm_symbol_size], (int16_t*)beam_weights[p][aa], (int16_t*)&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size], diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 2640a86240..e263c2c2cc 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -37,7 +37,6 @@ extern uint16_t prach_root_sequence_map_0_3[838]; extern uint16_t prach_root_sequence_map_abc[138]; extern uint16_t nr_du[838]; -extern int16_t nr_ru[2*839]; extern const char *prachfmt[9]; void init_prach_list(PHY_VARS_gNB *gNB) { @@ -540,7 +539,7 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, uint16_t rootSequenceIndex; int numrootSequenceIndex; uint8_t restricted_set; - uint8_t n_ra_prb; + uint8_t n_ra_prb=0xFF; int16_t *prachF=NULL; int nb_rx; diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index c7f6bba473..b8025a828b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -353,4 +353,5 @@ 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); + #endif /*__NR_TRANSPORT__H__*/ diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 3070d1a793..7006b54c29 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -266,8 +266,14 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, double Coderate;// = 0.0; uint8_t dmrs_Type = harq_process->dmrsConfigType; - AssertFatal(dmrs_Type == 1 || dmrs_Type == 2,"Illegal dmrs_type %d\n",dmrs_Type); - uint8_t nb_re_dmrs = (dmrs_Type==1)?6:4; // should be changed based on MAC parameters + AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type); + uint8_t nb_re_dmrs; + if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups; + } + else { + nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; + } uint16_t dmrs_length = get_num_dmrs(harq_process->dlDmrsSymbPos); AssertFatal(dmrs_length == 1 || dmrs_length == 2,"Illegal dmrs_length %d\n",dmrs_length); @@ -805,7 +811,12 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, //nfapi_nr_config_request_t *cfg = &phy_vars_ue->nrUE_config; //uint8_t dmrs_type = cfg->pdsch_config.dmrs_type.value; - uint8_t nb_re_dmrs = 12;//(dmrs_type==1)?6:4; + uint8_t nb_re_dmrs; + if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) + nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups; + else + nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups; + uint16_t length_dmrs = get_num_dmrs(dl_config_pdu->dlDmrsSymbPos); uint32_t i,j; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 996bd93a76..f792e1f4c6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -134,7 +134,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, int avgs = 0;// rb; NR_DL_UE_HARQ_t *dlsch0_harq, *dlsch1_harq = NULL; - uint8_t beamforming_mode; + uint8_t beamforming_mode = 0; int32_t **rxdataF_comp_ptr; int32_t **dl_ch_mag_ptr; @@ -162,24 +162,34 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, pdsch_vars = ue->pdsch_vars_SI; dlsch = &ue->dlsch_SI[eNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - beamforming_mode = 0; + break; case RA_PDSCH: pdsch_vars = ue->pdsch_vars_ra; dlsch = &ue->dlsch_ra[eNB_id]; dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - beamforming_mode = 0; + + // WIP TBR Hotfix + memcpy((void*)&pdsch_vars[eNB_id]->dl_ch_estimates[0][ue->frame_parms.ofdm_symbol_size*2], (void*)&ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_estimates[0][ue->frame_parms.ofdm_symbol_size*2], ue->frame_parms.ofdm_symbol_size*sizeof(int32_t)); break; case PDSCH: pdsch_vars = ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]]; dlsch = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id]; - beamforming_mode = ue->transmission_mode[eNB_id] < 7 ? 0 :ue->transmission_mode[eNB_id]; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; dlsch1_harq = dlsch[1]->harq_processes[harq_pid]; + beamforming_mode = ue->transmission_mode[eNB_id] < 7 ? 0 :ue->transmission_mode[eNB_id]; + break; + + default: + LOG_E(PHY, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type); + return -1; + break; + } + + if (dlsch1_harq){ //printf("status TB0 = %d, status TB1 = %d \n", dlsch[0]->harq_processes[harq_pid]->status, dlsch[1]->harq_processes[harq_pid]->status); LOG_D(PHY,"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", frame, nr_tti_rx, symbol, harq_pid, dlsch0_harq->status, dlsch1_harq->status); @@ -191,47 +201,51 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, dlsch1_harq = dlsch[codeword_TB1]->harq_processes[harq_pid]; #ifdef DEBUG_HARQ - printf("[DEMOD] I am assuming both TBs are active\n"); + printf("[DEMOD] I am assuming both TBs are active, in cw0 %d and cw1 %d \n", codeword_TB0, codeword_TB1); #endif } else if ((dlsch0_harq->status == ACTIVE) && (dlsch1_harq->status != ACTIVE) ) { codeword_TB0 = dlsch0_harq->codeword; - codeword_TB1 = -1; - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + dlsch0_harq = dlsch[codeword_TB0]->harq_processes[harq_pid]; dlsch1_harq = NULL; #ifdef DEBUG_HARQ - printf("[DEMOD] I am assuming only TB0 is active\n"); + printf("[DEMOD] I am assuming only TB0 is active, in cw %d \n", codeword_TB0); #endif } else if ((dlsch0_harq->status != ACTIVE) && (dlsch1_harq->status == ACTIVE)){ - codeword_TB0 = -1; codeword_TB1 = dlsch1_harq->codeword; dlsch0_harq = NULL; - dlsch1_harq = dlsch[1]->harq_processes[codeword_TB1]; + dlsch1_harq = dlsch[codeword_TB1]->harq_processes[harq_pid]; #ifdef DEBUG_HARQ - printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", dlsch1_harq->codeword); + printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", codeword_TB1); #endif - AssertFatal(1 == 0, "[UE][FATAL] DLSCH: TB0 not active and TB1 active case is not supported\n"); + LOG_E(PHY, "[UE][FATAL] DLSCH: TB0 not active and TB1 active case is not supported\n"); + return -1; } else { LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n", nr_tti_rx); return(-1); } + } else if (dlsch0_harq) { + if (dlsch0_harq->status == ACTIVE) + codeword_TB0 = dlsch0_harq->codeword; + dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - break; - - default: - AssertFatal(1 == 0, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type); - return(-1); - break; - + #ifdef DEBUG_HARQ + printf("[DEMOD] I am assuming only TB0 is active\n"); + #endif + } else { + LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n", nr_tti_rx); + return (-1); } - if (dlsch0_harq == NULL) - AssertFatal(1 == 0, "Done\n"); + if (dlsch0_harq == NULL) { + LOG_E(PHY, "Done\n"); + return -1; + } dlsch0_harq->Qm = nr_get_Qm_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table); dlsch0_harq->R = nr_get_code_rate_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table); @@ -2377,7 +2391,7 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF, for (aarx=0; aarxnb_antennas_rx; aarx++) { - k = frame_parms->first_carrier_offset + 12*start_rb; + k = frame_parms->first_carrier_offset + NR_NB_SC_PER_RB*start_rb; if (high_speed_flag == 1) dl_ch0 = &dl_ch_estimates[aarx][(2*(frame_parms->ofdm_symbol_size))]; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 79c542cd61..e4cab0b9a6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -44,18 +44,8 @@ //#define NR_PRACH_DEBUG 1 -extern uint16_t NCS_unrestricted_delta_f_RA_125[16]; -extern uint16_t NCS_restricted_TypeA_delta_f_RA_125[15]; -extern uint16_t NCS_restricted_TypeB_delta_f_RA_125[13]; -extern uint16_t NCS_unrestricted_delta_f_RA_5[16]; -extern uint16_t NCS_restricted_TypeA_delta_f_RA_5[16]; -extern uint16_t NCS_restricted_TypeB_delta_f_RA_5[14]; -extern uint16_t NCS_unrestricted_delta_f_RA_15[16]; extern uint16_t prach_root_sequence_map_0_3[838]; extern uint16_t prach_root_sequence_map_abc[138]; -extern int64_t table_6_3_3_2_2_prachConfig_Index [256][9]; -extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; -extern int64_t table_6_3_3_2_4_prachConfig_Index [256][10]; extern uint16_t nr_du[838]; extern int16_t nr_ru[2*839]; extern const char *prachfmt[9]; @@ -118,7 +108,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ else samp_count = (slot%(fp->slots_per_subframe/2)) ? fp->samples_per_slotN0 : fp->samples_per_slot0; - #if defined (OAI_USRP) + #ifdef OAI_USRP prach_start = (ue->rx_offset + slot*samp_count - ue->hw_timing_advance - ue->N_TA_offset); #else //normal case (simulation) prach_start = slot*samp_count - ue->N_TA_offset; @@ -208,14 +198,17 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ // now generate PRACH signal #ifdef NR_PRACH_DEBUG if (NCS>0) - LOG_I(PHY, "PRACH [UE %d] generate PRACH for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d\n", Mod_id, - rootSequenceIndex, - preamble_index, - prach_sequence_length == 0 ? prachfmt03[prach_fmt_id] : prachfmt[prach_fmt_id], + LOG_I(PHY, "PRACH [UE %d] generate PRACH in slot %d for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d msg1 frequency start %d\n", + Mod_id, + slot, + rootSequenceIndex, + preamble_index, + prach_sequence_length == 0 ? prachfmt03[prach_fmt_id] : prachfmt[prach_fmt_id], NCS, N_ZC, preamble_offset, - preamble_shift); + preamble_shift, + n_ra_prb); #endif // nsymb = (frame_parms->Ncp==0) ? 14:12; @@ -383,8 +376,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ } else { - //LOG_D(PHY, "PRACH [UE %d] in slot %d, format %d, msg1 frequency start %d startSymbol %d \n", Mod_id, slot, prachfmt[prach_fmt_id], n_ra_prb, prachStartSymbol); - switch (prach_fmt_id) { case 0: //A1 Ncp = 288/(1<N_RB_UL <= 100) AssertFatal(1==0,"N_RB_UL %d not supported for NR PRACH yet\n",fp->N_RB_UL); @@ -844,7 +837,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ //} //printf(" \n"); - #if defined(PRACH_WRITE_OUTPUT_DEBUG) + #ifdef PRACH_WRITE_OUTPUT_DEBUG LOG_M("prach_tx0.m", "prachtx0", prach+(Ncp<<1), prach_len-Ncp, 1, 1); LOG_M("Prach_txsig.m","txs",(int16_t*)(&ue->common_vars.txdata[0][prach_start]), 2*(prach_start+prach_len), 1, 1) #endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 6b2d5e7255..6ffb6f21a3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -292,6 +292,8 @@ typedef struct { uint16_t dlDmrsSymbPos; /// DMRS Configuration Type uint8_t dmrsConfigType; + // Number of DMRS CDM groups with no data + uint8_t n_dmrs_cdm_groups; /// Starting Symbol number uint16_t start_symbol; /// Current subband PMI allocation diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index fbb30632f6..b1c549530d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -100,7 +100,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot); - uint32_t available_bits, TBS; + uint32_t available_bits; uint8_t mod_order, cwd_index, num_of_codewords, l; uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; uint32_t ***pusch_dmrs; @@ -113,7 +113,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, int ap, start_symbol, Nid_cell, i; int sample_offsetF, N_RE_prime, N_PRB_oh; uint16_t ul_dmrs_symb_pos; - uint8_t data_existing =0; uint8_t L_ptrs, K_ptrs; // PTRS parameters uint16_t beta_ptrs; // PTRS parameter related to power control @@ -121,7 +120,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *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]; // ptrs_UplinkConfig_t *ptrs_Uplink_Config = &UE->pusch_config.dmrs_UplinkConfig.ptrs_UplinkConfig; num_of_codewords = 1; // tmp assumption @@ -171,54 +169,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, 0, harq_process_ul_ue->pusch_pdu.nrOfLayers); - uint8_t access_mode = SCHEDULED_ACCESS; - - //-----------------------------------------------------// - // to be removed later when MAC is ready - - if (harq_process_ul_ue != NULL){ - TBS = harq_process_ul_ue->pusch_pdu.pusch_data.tb_size; - data_existing = 0; - - if (IS_SOFTMODEM_NOS1){ - data_existing = nr_ue_get_sdu(UE->Mod_id, UE->CC_id, frame, - slot, 0, ulsch_input_buffer, TBS/8, &access_mode); - //IP traffic to be transmitted - if(data_existing){ - //harq_process_ul_ue->a = (unsigned char*)calloc(harq_process_ul_ue->TBS/8, sizeof(unsigned char)); - memcpy(harq_process_ul_ue->a, ulsch_input_buffer, TBS/8); - } - } - //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity - if (!IS_SOFTMODEM_NOS1 || !data_existing) { - //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid - //and block this traffic from being forwarded to the upper layers at the gNB - LOG_D(PHY, "Random data to be tranmsitted: \n"); - - //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) - //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should - //have a valid LCID (nr_process_mac_pdu function) - harq_process_ul_ue->a[0] = 0x31; - - for (i = 1; i < TBS / 8; i++) { - harq_process_ul_ue->a[i] = (unsigned char) rand(); - //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); - } - } -#ifdef DEBUG_MAC_PDU - LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", TBS/8); - for (i = 0; i < TBS / 8; i++) { - printf("%02x",harq_process_ul_ue->a[i]); - } - printf("\n"); -#endif - } else { - LOG_E(PHY, "[phy_procedures_nrUE_TX] harq_process_ul_ue is NULL !!\n"); - return; - } - - //-----------------------------------------------------// - /////////////////////////ULSCH coding///////////////////////// /////////// @@ -471,7 +421,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /////////// //////////////////////////////////////////////////////////////////////// - LOG_D(PHY, "Is data existing ?: %d \n", data_existing); } diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index b2ee4a2f3b..5b7a39da31 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -963,7 +963,7 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint64_t b[16]; // limit to 1024-bit encoded length // M_bit is the number of bits of block b (payload after encoding) uint16_t M_bit; - nr_uci_encoding(payload,nr_bit,pucch_format2_nr,0,nrofSymbols,nrofPRB,1,0,0,(void*)b,&M_bit); + nr_uci_encoding(payload,nr_bit,pucch_format2_nr,0,nrofSymbols,nrofPRB,1,0,0,&b[0],&M_bit); /* * Implementing TS 38.211 * Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2) @@ -985,7 +985,7 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, /* * Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2 */ - nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,b,btilde); + nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,&b[0],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 @@ -1154,7 +1154,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, //nrofPRB = 2; // only for test purposes if (fmt == pucch_format4_nr) nrofPRB = 1; - nr_uci_encoding(payload,nr_bit,fmt,is_pi_over_2_bpsk_enabled,nrofSymbols,nrofPRB,n_SF_PUCCH_s,intraSlotFrequencyHopping,add_dmrs,(void*)b,&M_bit); + nr_uci_encoding(payload,nr_bit,fmt,is_pi_over_2_bpsk_enabled,nrofSymbols,nrofPRB,n_SF_PUCCH_s,intraSlotFrequencyHopping,add_dmrs,&b[0],&M_bit); /* * Implementing TS 38.211 * Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4) @@ -1176,7 +1176,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, /* * Implementing TS 38.211 Subclause 6.3.2.6.1 scrambling formats 3 and 4 */ - nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,b,btilde); + nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,&b[0],btilde); /* * Implementing TS 38.211 Subclause 6.3.2.6.2 modulation formats 3 and 4 * diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index dfb148d34e..44d7b93ae2 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -26,6 +26,7 @@ #include #include "nr_phy_scope.h" #include "executables/nr-softmodem-common.h" +#include "executables/softmodem-common.h" #include #define TPUT_WINDOW_LENGTH 100 @@ -400,7 +401,8 @@ static void *scope_thread_gNB(void *arg) { // FILE *gNB_stats = fopen("gNB_stats.txt", "w"); //#endif size_t stksize=0; - pthread_attr_t atr= {0}; + pthread_attr_t atr; + pthread_attr_init(&atr); pthread_attr_getstacksize(&atr, &stksize); pthread_attr_setstacksize(&atr,32*1024*1024 ); sleep(3); // no clean interthread barriers @@ -768,6 +770,15 @@ void nrUEinitScope(PHY_VARS_NR_UE *ue) { threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW); } + +void nrscope_autoinit(void *dataptr) { + AssertFatal( (IS_SOFTMODEM_GNB_BIT||IS_SOFTMODEM_5GUE_BIT),"Scope cannot find NRUE or GNB context"); + + if (IS_SOFTMODEM_GNB_BIT) + gNBinitScope(dataptr); + else + nrUEinitScope(dataptr); +} // Kept to put back the functionality soon #if 0 //FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; @@ -795,6 +806,8 @@ static void reset_stats_gNB(FL_OBJECT *button, } } + + static FD_stats_form *create_form_stats_form(int ID) { FL_OBJECT *obj; FD_stats_form *fdui = calloc(( sizeof *fdui ),1); diff --git a/openair1/PHY/TOOLS/nr_phy_scope.h b/openair1/PHY/TOOLS/nr_phy_scope.h index 429537141a..84b9e66908 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.h +++ b/openair1/PHY/TOOLS/nr_phy_scope.h @@ -40,8 +40,6 @@ typedef struct { PHY_VARS_gNB *gNB; } scopeParms_t; -void gNBinitScope(scopeParms_t *p); -void nrUEinitScope(PHY_VARS_NR_UE *ue); extern RAN_CONTEXT_t RC; #endif diff --git a/openair1/PHY/TOOLS/phy_scope_interface.c b/openair1/PHY/TOOLS/phy_scope_interface.c index 835fb4ea7b..af237b2325 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.c +++ b/openair1/PHY/TOOLS/phy_scope_interface.c @@ -37,10 +37,10 @@ #define SOFTSCOPE_ENDFUNC_IDX 0 static loader_shlibfunc_t scope_fdesc[]= {{"end_forms",NULL}}; -int load_softscope(char *exectype) { +int load_softscope(char *exectype, void *initarg) { char libname[64]; sprintf(libname,"%.10sscope",exectype); - return load_module_shlib(libname,scope_fdesc,1,NULL); + return load_module_shlib(libname,scope_fdesc,1,initarg); } int end_forms(void) { diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index 779a57a720..adf04d5ea4 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -31,5 +31,5 @@ */ -int load_softscope(char *exectype); +int load_softscope(char *exectype, void *initarg); int end_forms(void) ; diff --git a/openair1/PHY/TOOLS/readme.md b/openair1/PHY/TOOLS/readme.md new file mode 100644 index 0000000000..f6671acc6d --- /dev/null +++ b/openair1/PHY/TOOLS/readme.md @@ -0,0 +1,12 @@ + +To use the scope, run the xNB or the UE with option "-d" + +Usage in gdb +In gdb, when you break, you can refresh immediatly the scope view by calling the display function. +The first paramter is the graph context, nevertheless we keep the last value for a dirty call in gdb (so you can use '0') + +Example with no variable known +phy_scope_nrUE(0, PHY_vars_UE_g[0][0], 0, 0, 0) + +or +phy_scope_gNB(0, phy_vars_gnb, phy_vars_ru, UE_id) diff --git a/openair1/PHY/phy_vars.h b/openair1/PHY/phy_vars.h index a74d148479..5e2be8bd8f 100644 --- a/openair1/PHY/phy_vars.h +++ b/openair1/PHY/phy_vars.h @@ -59,10 +59,10 @@ const short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; unsigned char NB_RU=0; #ifndef OPENAIR2 -unsigned char NB_eNB_INST=0; -uint16_t NB_UE_INST=0; -unsigned char NB_RN_INST=0; -unsigned char NB_INST=0; +//unsigned char NB_eNB_INST=0; +//uint16_t NB_UE_INST=0; +//unsigned char NB_RN_INST=0; +//unsigned char NB_INST=0; #endif int number_of_cards; diff --git a/openair1/PHY/phy_vars_nr_ue.h b/openair1/PHY/phy_vars_nr_ue.h index 1843d8d5bc..baa64561f0 100644 --- a/openair1/PHY/phy_vars_nr_ue.h +++ b/openair1/PHY/phy_vars_nr_ue.h @@ -138,4 +138,4 @@ uint8_t scrambling_lut[65536*16] __attribute__((aligned(32))); uint8_t max_ldpc_iterations=4; uint8_t max_turbo_iterations=4; -#endif /*__PHY_VARS_H__ */ +#endif diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 996cad9d1d..974441e5db 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -159,6 +159,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ gNB->dlsch[i][0]->rnti=0; gNB->dlsch[i][0]->harq_mask=0; } + gNB->pbch_configured=0; for (int i=0;issb_config.scs_common, check_slot = 0; - - if (cfg->cell_config.frame_duplex_type == FDD) { - return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT); - } - - if (nr_frame%2 == 0) { - for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { - check_slot++; - } - } - - if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { - return (NR_UPLINK_SLOT); - } - - check_slot = 0; - - for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) { - check_slot++; - } - } - - if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { - return (NR_DOWNLINK_SLOT); - } else { - return (NR_MIXED_SLOT); - } - } else { - for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1< /************** DEFINE ********************************************/ #define TDD_CONFIG_NB_FRAMES (2) @@ -77,10 +76,9 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms); * @param frame_parms NR DL Frame parameters * @param nr_frame : frame number * @param nr_tti : slot number - @returns nr_slot_t : downlink or uplink */ + @returns int : downlink, uplink or mixed slot type*/ -nr_slot_t nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti); -int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti); +int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti); /** \brief This function frees tdd configuration for nr * @param frame_parms NR DL Frame parameters diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index f852ae4ae1..ea73f2fecc 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -106,6 +106,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ dlsch0_harq->start_symbol = dlsch_config_pdu->start_symbol; dlsch0_harq->dlDmrsSymbPos = dlsch_config_pdu->dlDmrsSymbPos; dlsch0_harq->dmrsConfigType = dlsch_config_pdu->dmrsConfigType; + dlsch0_harq->n_dmrs_cdm_groups = dlsch_config_pdu->n_dmrs_cdm_groups; dlsch0_harq->mcs = dlsch_config_pdu->mcs; dlsch0_harq->rvidx = dlsch_config_pdu->rv; dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH; @@ -147,12 +148,32 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ // pusch config pdu pusch_config_pdu = &ul_config->ul_config_list[i].pusch_config_pdu; current_harq_pid = pusch_config_pdu->pusch_data.harq_process_id; - nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch0->harq_processes[current_harq_pid]->pusch_pdu; + NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch0->harq_processes[current_harq_pid]; - memcpy(pusch_pdu, pusch_config_pdu, sizeof(nfapi_nr_ue_pusch_pdu_t)); + if (harq_process_ul_ue){ + + nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &harq_process_ul_ue->pusch_pdu; + + memcpy(pusch_pdu, pusch_config_pdu, sizeof(nfapi_nr_ue_pusch_pdu_t)); + + ulsch0->f_pusch = pusch_config_pdu->absolute_delta_PUSCH; + + if (scheduled_response->tx_request){ + fapi_nr_tx_request_body_t *tx_req_body = scheduled_response->tx_request->tx_request_body; + + //harq_process_ul_ue->a = (unsigned char*)calloc(TBS/8, sizeof(unsigned char)); + memcpy(harq_process_ul_ue->a, tx_req_body->pdu, tx_req_body->pdu_length); + + harq_process_ul_ue->status = ACTIVE; + } + + } else { + + LOG_E(PHY, "[phy_procedures_nrUE_TX] harq_process_ul_ue is NULL !!\n"); + return -1; + + } - ulsch0->f_pusch = pusch_config_pdu->absolute_delta_PUSCH; - ulsch0->harq_processes[current_harq_pid]->status = ACTIVE; break; case (FAPI_NR_UL_CONFIG_TYPE_PUCCH): @@ -214,9 +235,6 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ } else { } - if (scheduled_response->tx_request != NULL){ - } else { - } } return 0; diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr.h b/openair1/SCHED_NR_UE/phy_frame_config_nr.h index a7e78397fe..3669239578 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr.h +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr.h @@ -62,10 +62,18 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms); * @param frame_parms NR DL Frame parameters * @param nr_frame : frame number * @param nr_tti : slot number - @returns nr_slot_t : downlink or uplink */ + @returns int : downlink or uplink */ int slot_select_nr(NR_DL_FRAME_PARMS *frame_parms, int nr_frame, int nr_tti); +/** \brief This function checks nr UE slot direction : downlink or uplink + * @param cfg : FAPI Config Request + * @param nr_frame : frame number + * @param nr_tti : slot number + @returns int : downlink, uplink or mixed slot type */ + +int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti); + /** \brief This function frees tdd configuration for nr * @param frame_parms NR DL Frame parameters @returns none */ diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c new file mode 100644 index 0000000000..640ffb4ac3 --- /dev/null +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c @@ -0,0 +1,99 @@ +/* + * 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 + */ + +/*********************************************************************** +* +* FILENAME : phy_frame_configuration_nr_ue.c +* +* DESCRIPTION : functions related to FDD/TDD configuration for NR +* see TS 38.213 11.1 Slot configuration +* and TS 38.331 for RRC configuration +* +************************************************************************/ + +#include "PHY/defs_nr_UE.h" + +/******************************************************************* +* +* NAME : nr_ue_slot_select +* +* DESCRIPTION : function for the UE equivalent to nr_slot_select +* +*********************************************************************/ + +int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti) { + /* for FFD all slot can be considered as an uplink */ + int mu = cfg->ssb_config.scs_common, check_slot = 0; + + if (cfg->cell_config.frame_duplex_type == FDD) { + return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT); + } + + if (nr_frame%2 == 0) { + for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { + check_slot++; + } + } + + if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + return (NR_UPLINK_SLOT); + } + + check_slot = 0; + + for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) { + check_slot++; + } + } + + if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + return (NR_DOWNLINK_SLOT); + } else { + return (NR_MIXED_SLOT); + } + } else { + for(int symbol_count=0; symbol_counttdd_table.max_tdd_periodicity_list[((1<tdd_table.max_tdd_periodicity_list[((1<do_ra==1) { - if ((ue->UE_mode[gNB_id] == PRACH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) { + if ((ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) { nr_ue_prach_procedures(ue, proc, gNB_id, mode); } } @@ -3289,9 +3289,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, NR_UE_PDSCH *pdsch_vars; uint8_t is_cw0_active = 0; uint8_t is_cw1_active = 0; - uint8_t dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; - uint8_t nb_re_dmrs = (dmrs_type==NFAPI_NR_DMRS_TYPE1)?6:4; // TODO: should changed my mac - uint16_t length_dmrs = 1; //cfg->pdsch_config.dmrs_max_length.value; + uint8_t dmrs_type, nb_re_dmrs; + uint16_t length_dmrs = 1; uint16_t nb_symb_sch = 9; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind; @@ -3316,6 +3315,13 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, is_cw0_active = dlsch0->harq_processes[harq_pid]->status; nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols; start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol; + dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType; + if (dmrs_type==NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; + } + else { + nb_re_dmrs = 4*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups; + } if(dlsch1) is_cw1_active = dlsch1->harq_processes[harq_pid]->status; @@ -4606,6 +4612,8 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t if (ue->prach_cnt == 3) ue->prach_cnt = 0; + } else if (nr_prach == 2) { + nr_ra_succeeded(mod_id, ue->CC_id, gNB_id); } // if we're calibrating the PRACH kill the pointer to its resources so that the RA protocol doesn't continue diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 9374050e58..b4069237b8 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -478,8 +478,9 @@ int main(int argc, char **argv) harq_process->Qm = mod_order; harq_process->rvidx = rvidx; harq_process->R = rate; - harq_process->dmrsConfigType = 1; + harq_process->dmrsConfigType = NFAPI_NR_DMRS_TYPE1; harq_process->dlDmrsSymbPos = 4; + harq_process->n_dmrs_cdm_groups = 1; printf("harq process ue mcs = %d Qm = %d, symb %d\n", harq_process->mcs, harq_process->Qm, nb_symb_sch); unsigned char *test_input; test_input = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 0c0e57462f..0ecb8f2c36 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -756,7 +756,8 @@ int main(int argc, char **argv) scheduled_response.slot = slot; scheduled_response.dl_config = NULL; scheduled_response.ul_config = &ul_config; - scheduled_response.dl_config = NULL; + scheduled_response.tx_request = (fapi_nr_tx_request_t *) malloc(sizeof(fapi_nr_tx_request_t)); + scheduled_response.tx_request->tx_request_body = (fapi_nr_tx_request_body_t *) malloc(sizeof(fapi_nr_tx_request_body_t)); ul_config.slot = slot; ul_config.number_pdus = 1; diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index 55dc85b050..505016b279 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -45,8 +45,12 @@ static mapping channelmod_names[] = { }; static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt); +static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt); +static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt); static telnetshell_cmddef_t channelmod_cmdarray[] = { - {"show","",channelmod_show_cmd}, + {"help","",channelmod_print_help}, + {"show","",channelmod_show_cmd}, + {"modify"," ",channelmod_modify_cmd}, {"","",NULL}, }; @@ -56,14 +60,15 @@ static telnetshell_vardef_t channelmod_vardef[] = { static double snr_dB=25; static double sinr_dB=0; - +static unsigned int max_chan; +static channel_desc_t** defined_channels; void fill_channel_desc(channel_desc_t *chan_desc, uint8_t nb_tx, uint8_t nb_rx, uint8_t nb_taps, uint8_t channel_length, double *amps, - double *delays, + double *delays, struct complex **R_sqrt, double Td, double sampling_rate, @@ -88,6 +93,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, if (delays==NULL) { chan_desc->delays = (double *) malloc(nb_taps*sizeof(double)); + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_DELAY ; delta_tau = Td/nb_taps; for (i=0; iR_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_NTAPS ; for (i = 0; iR_sqrt[i] = (struct complex *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); - + chan_desc->R_sqrt[i] = (struct complex *) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -140,7 +145,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, } } else { chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); - + for (i = 0; iR_sqrt[i] = (struct complex*) calloc(nb_tx*nb_rx*nb_tx*nb_rx,sizeof(struct complex)); //chan_desc->R_sqrt = (struct complex*)&R_sqrt[i][0]; @@ -170,7 +175,7 @@ void fill_channel_desc(channel_desc_t *chan_desc, double mbsfn_delays[] = {0,.03,.15,.31,.37,1.09,12.490,12.52,12.64,12.80,12.86,13.58,27.49,27.52,27.64,27.80,27.86,28.58}; double mbsfn_amps_dB[] = {0,-1.5,-1.4,-3.6,-0.6,-7.0,-10,-11.5,-11.4,-13.6,-10.6,-17.0,-20,-21.5,-21.4,-23.6,-20.6,-27}; -double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250}; +double scm_c_delays[] = {0, 0.0125, 0.0250, 0.3625, 0.3750, 0.3875, 0.2500, 0.2625, 0.2750, 1.0375, 1.0500, 1.0625, 2.7250, 2.7375, 2.7500, 4.6000, 4.6125, 4.6250}; double scm_c_amps_dB[] = {0.00, -2.22, -3.98, -1.86, -4.08, -5.84, -1.08, -3.30, -5.06, -9.08, -11.30, -13.06, -15.14, -17.36, -19.12, -20.64, -22.85, -24.62}; double tdl_a_delays[] = {0.0000, @@ -498,12 +503,24 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, double forgetting_factor, int32_t channel_offset, double path_loss_dB) { - channel_desc_t *chan_desc = (channel_desc_t *)malloc(sizeof(channel_desc_t)); + channel_desc_t *chan_desc = (channel_desc_t *)calloc(1,sizeof(channel_desc_t)); + for(int i=0; ichan_idx=i; + break; + } + else { + AssertFatal(i<(max_chan-1), + "No more channel descriptors available, increase channelmod.max_chan parameter above %u\n",max_chan); + } + } uint16_t i,j; double sum_amps; double aoa,ricean_factor,Td,maxDoppler; int channel_length,nb_taps; + chan_desc->modelid = channel_model; chan_desc->nb_tx = nb_tx; chan_desc->nb_rx = nb_rx; chan_desc->sampling_rate = sampling_rate; @@ -537,7 +554,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -575,9 +592,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; } else { + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); - + for (j = 0; jR_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -596,7 +614,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -634,6 +652,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, for (i = 0; i<6; i++) chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0]; } else { + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); @@ -647,6 +666,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, } break; +<<<<<<< HEAD case TDL_A: case TDL_B: @@ -742,13 +762,16 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, break; +======= + +>>>>>>> origin/develop case EPA: chan_desc->nb_taps = 7; chan_desc->Td = .410; chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -767,7 +790,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, for (i = 0; ich[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); - + for (i = 0; ichF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); @@ -781,7 +804,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; } else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); @@ -802,7 +825,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -848,7 +871,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n"); } }*/ - break; + break; case EPA_high: chan_desc->nb_taps = 7; @@ -856,7 +879,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -910,7 +933,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -964,7 +987,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -997,8 +1020,8 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; } else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); - - for (i = 0; i<6; i++) { + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; + for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); for (j = 0; jchannel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -1051,7 +1074,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0]; } else { chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); @@ -1072,7 +1095,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td)); sum_amps = 0; chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ; for (i = 0; inb_taps; i++) { chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -1099,7 +1122,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex)); chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex *)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6; for (i = 0; i<6; i++) { chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex)); @@ -1610,10 +1633,37 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, chan_desc->nb_paths = 10; return(chan_desc); } - + void free_channel_desc_scm(channel_desc_t *ch) { // Must be made cleanly, a lot of leaks... - free(ch); + defined_channels[ch->chan_idx]=NULL; + if(ch->free_flags&CHANMODEL_FREE_AMPS) + free(ch->amps); + for (int i = 0; inb_tx*ch->nb_rx; i++) { + free(ch->ch[i]); + free(ch->chF[i]); + } + + for (int i = 0; inb_taps; i++) { + free(ch->a[i]); + } + if(ch->free_flags&CHANMODEL_FREE_DELAY) + free(ch->delays); + if(ch->free_flags&CHANMODEL_FREE_RSQRT_6) + for (int i = 0; i<6; i++) + free(ch->R_sqrt[i]); + if(ch->free_flags&CHANMODEL_FREE_RSQRT_NTAPS) + for (int i = 0; inb_taps;i++) + free(ch->R_sqrt[i]); + free(ch->R_sqrt); + free(ch->ch); + free(ch->chF); + free(ch->a); + free(ch); +} + +void set_channeldesc_owner(channel_desc_t *cdesc, uint32_t module_id) { + cdesc->module_id=module_id; } int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { @@ -1726,11 +1776,11 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0; for (l=0; lnb_taps; l++) { - if ((k - (desc->delays[l]*desc->sampling_rate) - NB_SAMPLES_CHANNEL_OFFSET) == 0) + if ((k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset) == 0) s = 1.0; else - s = sin(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - NB_SAMPLES_CHANNEL_OFFSET))/ - (M_PI*(k - (desc->delays[l]*desc->sampling_rate) - NB_SAMPLES_CHANNEL_OFFSET)); + s = sin(M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset))/ + (M_PI*(k - (desc->delays[l]*desc->sampling_rate) - desc->channel_offset)); desc->ch[aarx+(aatx*desc->nb_rx)][k].x += s*desc->a[l][aarx+(aatx*desc->nb_rx)].x; desc->ch[aarx+(aatx*desc->nb_rx)][k].y += s*desc->a[l][aarx+(aatx*desc->nb_rx)].y; @@ -1753,7 +1803,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { return (0); } - + double N_RB2sampling_rate(uint16_t N_RB) { double sampling_rate; @@ -1805,22 +1855,125 @@ double N_RB2channel_bandwidth(uint16_t N_RB) { LOG_E(PHY,"Unknown N_PRB\n"); return(-1); } - return(channel_bandwidth); +} + + +static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt ) { + prnt("channelmod commands can be used to display or modify channel models parameters\n"); + prnt("channelmod show predef: display predefined model algorithms available in oai\n"); + prnt("channelmod show current: display the currently used models in the running executable\n"); + prnt("channelmod modify : set the specified parameters in a current model to the given value\n"); + prnt(" specifies the model, the show current model command can be used to list the current models indexes\n"); + prnt(" can be one of \"riceanf\", \"aoa\", \"randaoa\", \"ploss\", \"offset\", \"forgetf\"\n"); + return CMDSTATUS_FOUND; } + +static void display_channelmodel(channel_desc_t *cd,int debug, telnet_printfunc_t prnt) { + char *module_id_str[]=MODULEID_STR_INIT; + if (cd->module_id != 0) { + prnt("model owner: %s\n",module_id_str[cd->module_id]); + } + prnt("nb_tx: %i nb_rx: %i taps: %i bandwidth: %lf sampling: %lf\n",cd->nb_tx, cd->nb_rx, cd->nb_taps, cd->channel_bandwidth, cd->sampling_rate); + prnt("channel length: %i Max path delay: %lf ricean fact.: %lf angle of arrival: %lf (randomized:%s)\n", + cd->channel_length, cd->Td, cd->ricean_factor, cd->aoa, (cd->random_aoa?"Yes":"No")); + prnt("max Doppler: %lf path loss: %lf rchannel offset: %i forget factor; %lf\n", + cd->max_Doppler, cd->path_loss_dB, cd->channel_offset, cd->forgetting_factor); + prnt("Initial phase: %lf nb_path: %i \n", + cd->ip, cd->nb_paths); + for (int i=0; inb_taps ; i++) { + prnt("taps: %i lin. ampli. : %lf delay: %lf \n",i,cd->amps[i], cd->delays[i]); + } +} + + static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt) { - for(int i=0; channelmod_names[i].name != NULL ; i++) { - prnt(" %i %s\n", i, map_int_to_str(channelmod_names,i )); - } + char *subcmd=NULL; + int s = sscanf(buff,"%ms\n",&subcmd); - return 0; + if (s>0) { + if ( strcmp(subcmd,"predef") == 0) { + for (int i=0; channelmod_names[i].name != NULL ; i++) { + prnt(" %i %s\n", i, map_int_to_str(channelmod_names,i )); + } + } else if ( strcmp(subcmd,"current") == 0) { + for (int i=0; i < max_chan ; i++) { + if (defined_channels[i] != NULL) { + prnt("model %i %s: \n----------------\n", i, map_int_to_str(channelmod_names,defined_channels[i]->modelid)); + display_channelmodel(defined_channels[i],debug,prnt); + } + } + } else { + channelmod_print_help(buff, debug, prnt); + } + free(subcmd); + } + return CMDSTATUS_FOUND; } -int modelid_fromname(char *modelname) { - int modelid=map_str_to_int(channelmod_names,modelname); - AssertFatal(modelid>0, - "random_channel.c: Error channel model %s unknown\n",modelname); + + +static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt) { + char *param=NULL, *value=NULL; + int cd_id= -1; + int s = sscanf(buff,"%i %ms %ms \n",&cd_id,¶m, &value); + if (cd_id<0 || cd_id >= max_chan) { + prnt("ERROR, %i: Channel model id outof range (0-%i)\n",cd_id,max_chan-1); + return CMDSTATUS_FOUND; + } + if (defined_channels[cd_id]==NULL) { + prnt("ERROR, %i: Channel model has not been set\n",cd_id); + return CMDSTATUS_FOUND; + } + + if (s==3) { + if ( strcmp(param,"riceanf") == 0) { + double dbl = atof(value); + if (dbl <0 || dbl > 1) + prnt("ERROR: ricean factor range: 0 to 1, %lf is outof range\n",dbl); + else + defined_channels[cd_id]->ricean_factor=dbl; + } else if ( strcmp(param,"aoa") == 0) { + double dbl = atof(value); + if (dbl <0 || dbl >6.28) + prnt("ERROR: angle of arrival range: 0 to 2*Pi, %lf is outof range\n",dbl); + else + defined_channels[cd_id]->aoa=dbl; + } else if ( strcmp(param,"randaoa") == 0) { + int i = atoi(value); + if (i!=0 && i!=1) + prnt("ERROR: randaoa is a boolean, must be 0 or 1\n"); + else + defined_channels[cd_id]->random_aoa=i; + } else if ( strcmp(param,"ploss") == 0) { + double dbl = atof(value); + defined_channels[cd_id]->path_loss_dB=dbl; + } else if ( strcmp(param,"offset") == 0) { + int i = atoi(value); + defined_channels[cd_id]->channel_offset=i; + } else if ( strcmp(param,"forgetf") == 0) { + double dbl = atof(value); + if (dbl <0 || dbl > 1) + prnt("ERROR: forgetting factor range: 0 to 1 (disable variation), %lf is outof range\n",dbl); + else + defined_channels[cd_id]->forgetting_factor=dbl; + } else { + prnt("ERROR: %s, unknown channel parameter\n",param); + return CMDSTATUS_FOUND; + } + display_channelmodel(defined_channels[cd_id],debug,prnt); + free(param); + free(value); + random_channel(defined_channels[cd_id],false); + } + return CMDSTATUS_FOUND; +} + +int modelid_fromname(char *modelname) { + int modelid=map_str_to_int(channelmod_names,modelname); + if (modelid < 0) + LOG_E(OCM,"random_channel.c: Error channel model %s unknown\n",modelname); return modelid; } @@ -1836,6 +1989,9 @@ void init_channelmod(void) { paramdef_t channelmod_params[] = CHANNELMOD_PARAMS_DESC; int ret = config_get( channelmod_params,sizeof(channelmod_params)/sizeof(paramdef_t),CHANNELMOD_SECTION); AssertFatal(ret >= 0, "configuration couldn't be performed"); + defined_channels=calloc(max_chan,sizeof( channel_desc_t*)); + AssertFatal(defined_channels!=NULL, "couldn't allocate %u channel descriptors\n",max_chan); + /* look for telnet server, if it is loaded, add the channel modeling commands to it */ add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h index 2eab288b5a..2f5ab99b41 100644 --- a/openair1/SIMULATION/TOOLS/sim.h +++ b/openair1/SIMULATION/TOOLS/sim.h @@ -40,6 +40,16 @@ The present clause specifies several numerical functions for testing of digital #define NB_SAMPLES_CHANNEL_OFFSET 4 +typedef enum { + UNSPECIFIED_MODID=0, + RFSIMU_MODULEID=1 +} channelmod_moduleid_t; +#define MODULEID_STR_INIT {"","rfsimulator"} + +#define CHANMODEL_FREE_DELAY 1<<0 +#define CHANMODEL_FREE_RSQRT_6 1<<1 +#define CHANMODEL_FREE_RSQRT_NTAPS 1<<2 +#define CHANMODEL_FREE_AMPS 1<<3 typedef struct { ///Number of tx antennas uint8_t nb_tx; @@ -92,6 +102,14 @@ typedef struct { time_stats_t interp_time; time_stats_t interp_freq; time_stats_t convolution; + /// index in the channel descriptors array + unsigned int chan_idx; + /// id of the channel modeling algorithm + int modelid; + /// identifies channel descriptor owner (the module which created this descriptor) + channelmod_moduleid_t module_id; + /// flags to properly trigger memory free + unsigned int free_flags; } channel_desc_t; typedef struct { @@ -224,8 +242,9 @@ typedef enum { #define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n" #define CHANNELMOD_SECTION "channelmod" #define CHANNELMOD_PARAMS_DESC { \ - {"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB , defdblval:25, TYPE_DOUBLE, 0},\ - {"sinr_dB", NULL , 0 , dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\ + {"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0},\ + {"sinr_dB", NULL, 0 , dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\ + {"max_chan, CONFIG_HLP_MAX_CHAN", 0, uptr:&max_chan, defintval:10, TYPE_UINT, 0},\ } #include "platform_constants.h" @@ -262,9 +281,18 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, double forgetting_factor, int32_t channel_offset, double path_loss_dB); +/** +\brief free memory allocated for a model descriptor +\param ch points to the model, which cannot be used after calling this fuction +*/ +void free_channel_desc_scm(channel_desc_t *ch); - - +/** +\brief This set the ownerid of a model descriptor, can be later used to check what module created a channel model +\param cdesc points to the model descriptor +\param module_id identifies the channel model. should be define as a macro in simu.h +*/ +void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_id); /** \fn void random_channel(channel_desc_t *desc) \brief This routine generates a random channel response (time domain) according to a tapped delay line model. \param desc Pointer to the channel descriptor 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 603ff25198..f1daacbb65 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -49,18 +49,13 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB]; struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB]; -/* the slice config as kept in the underlying system */ -Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES]; -/* a structure that keeps updates which will be reflected in slice_config later */ -Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES]; -/* indicates whether sc_update contains new data */ -int perform_slice_config_update_count = 1; -/* queue of incoming new UE<>slice association commands */ -Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES]; -int n_ue_slice_assoc_updates = 0; -/* mutex for sc_update: do not receive new config and write it at the same time */ -pthread_mutex_t sc_update_mtx = PTHREAD_MUTEX_INITIALIZER; +/* Ringbuffer-related to slice configuration */ +struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB]; +struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB]; +/* Ringbuffer-related to slice configuration */ +struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB]; +struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB]; int flexran_agent_mac_stats_reply_ue(mid_t mod_id, Protocol__FlexUeStatsReport **ue_report, @@ -1354,6 +1349,33 @@ void flexran_agent_init_mac_agent(mid_t mod_id) { AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory for lfds library\n"); lfds700_ringbuffer_init_valid_on_current_logical_core(&ringbuffer_state[mod_id], dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL); + + struct lfds700_misc_prng_state scrng; + i = posix_memalign((void **) &slice_config_array[mod_id], + LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, + sizeof(struct lfds700_ringbuffer_element) * num_elements); + AssertFatal(i == 0, + "posix_memalign(): could not allocate aligned memory\n"); + lfds700_ringbuffer_init_valid_on_current_logical_core( + &slice_config_ringbuffer_state[mod_id], + slice_config_array[mod_id], + num_elements, + &scrng, + NULL); + + struct lfds700_misc_prng_state uarng; + i = posix_memalign((void **) &ue_assoc_array[mod_id], + LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, + sizeof(struct lfds700_ringbuffer_element) * num_elements); + AssertFatal(i == 0, + "posix_memalign(): could not allocate aligned memory\n"); + lfds700_ringbuffer_init_valid_on_current_logical_core( + &ue_assoc_ringbuffer_state[mod_id], + ue_assoc_array[mod_id], + num_elements, + &uarng, + NULL); + for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { for (j = 0; j < 8; j++) { if (RC.mac && RC.mac[mod_id]) @@ -1465,9 +1487,74 @@ void flexran_agent_fill_mac_cell_config(mid_t mod_id, uint8_t cc_id, conf->si_config->has_sfn = 1; } - /* get a pointer to the config which is maintained in the agent throughout - * its lifetime */ - conf->slice_config = flexran_agent_get_slice_config(mod_id); + conf->slice_config = malloc(sizeof(Protocol__FlexSliceConfig)); + if (conf->slice_config) { + protocol__flex_slice_config__init(conf->slice_config); + Protocol__FlexSliceConfig *sc = conf->slice_config; + + sc->dl = malloc(sizeof(Protocol__FlexSliceDlUlConfig)); + DevAssert(sc->dl); + protocol__flex_slice_dl_ul_config__init(sc->dl); + sc->dl->algorithm = flexran_get_dl_slice_algo(mod_id); + sc->dl->has_algorithm = 1; + sc->dl->n_slices = flexran_get_num_dl_slices(mod_id); + if (sc->dl->n_slices > 0) { + sc->dl->slices = calloc(sc->dl->n_slices, sizeof(Protocol__FlexSlice *)); + DevAssert(sc->dl->slices); + for (int i = 0; i < sc->dl->n_slices; ++i) { + sc->dl->slices[i] = malloc(sizeof(Protocol__FlexSlice)); + DevAssert(sc->dl->slices[i]); + protocol__flex_slice__init(sc->dl->slices[i]); + flexran_get_dl_slice(mod_id, i, sc->dl->slices[i], sc->dl->algorithm); + } + } else { + sc->dl->scheduler = flexran_get_dl_scheduler_name(mod_id); + } + + sc->ul = malloc(sizeof(Protocol__FlexSliceDlUlConfig)); + DevAssert(sc->ul); + protocol__flex_slice_dl_ul_config__init(sc->ul); + sc->ul->algorithm = flexran_get_ul_slice_algo(mod_id); + sc->ul->has_algorithm = 1; + sc->ul->n_slices = flexran_get_num_ul_slices(mod_id); + if (sc->ul->n_slices > 0) { + sc->ul->slices = calloc(sc->ul->n_slices, sizeof(Protocol__FlexSlice *)); + DevAssert(sc->ul->slices); + for (int i = 0; i < sc->ul->n_slices; ++i) { + sc->ul->slices[i] = malloc(sizeof(Protocol__FlexSlice)); + DevAssert(sc->ul->slices[i]); + protocol__flex_slice__init(sc->ul->slices[i]); + flexran_get_ul_slice(mod_id, i, sc->ul->slices[i], sc->ul->algorithm); + } + } else { + sc->ul->scheduler = flexran_get_ul_scheduler_name(mod_id); + } + } +} + +void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf) { + Protocol__FlexSliceConfig *sc = conf->slice_config; + for (int i = 0; i < sc->dl->n_slices; ++i) { + free(sc->dl->slices[i]); + sc->dl->slices[i] = NULL; + /* scheduler names are not freed: we assume we read them directly from the + * underlying memory and do not dispose it */ + } + free(sc->dl->slices); + /* scheduler name is not freed */ + free(sc->dl); + sc->dl = NULL; + for (int i = 0; i < sc->ul->n_slices; ++i) { + free(sc->ul->slices[i]); + sc->ul->slices[i] = NULL; + /* scheduler names are not freed */ + } + free(sc->ul->slices); + /* scheduler name is not freed */ + free(sc->ul); + sc->ul = NULL; + free(conf->slice_config); + conf->slice_config = NULL; } void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id, @@ -1481,10 +1568,12 @@ void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id, ue_conf->rnti = flexran_get_mac_ue_crnti(mod_id, ue_id); ue_conf->has_rnti = 1; - ue_conf->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, ue_id); - ue_conf->has_dl_slice_id = 1; - ue_conf->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, ue_id); - ue_conf->has_ul_slice_id = 1; + int dl_id = flexran_get_ue_dl_slice_id(mod_id, ue_id); + ue_conf->dl_slice_id = dl_id; + ue_conf->has_dl_slice_id = dl_id >= 0; + int ul_id = flexran_get_ue_ul_slice_id(mod_id, ue_id); + ue_conf->ul_slice_id = ul_id; + ue_conf->has_ul_slice_id = ul_id >= 0; ue_conf->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id, ue_id); ue_conf->has_ue_aggregated_max_bitrate_ul = 1; @@ -1565,6 +1654,15 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) LOG_E(FLEXRAN_AGENT, "MAC agent CM for eNB %d is not registered\n", mod_id); return -1; } + + lfds700_ringbuffer_cleanup(&ringbuffer_state[mod_id], NULL ); + free(dl_mac_config_array[mod_id]); + lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL ); + free(slice_config_array[mod_id]); + lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL ); + free(ue_assoc_array[mod_id]); + lfds700_misc_library_cleanup(); + AGENT_MAC_xface *xface = agent_mac_xface[mod_id]; xface->flexran_agent_send_sr_info = NULL; xface->flexran_agent_send_sf_trigger = NULL; @@ -1579,230 +1677,91 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) return 0; } - -void flexran_create_config_structures(mid_t mod_id) -{ - int i; - int n_dl = flexran_get_num_dl_slices(mod_id); - int m_ul = flexran_get_num_ul_slices(mod_id); - slice_config[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul); - sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul); - if (!slice_config[mod_id] || !sc_update[mod_id]) return; - - flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); - flexran_agent_read_slice_config(mod_id, sc_update[mod_id]); - for (i = 0; i < n_dl; i++) { - flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]); +void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) { + if (slice_config->dl) { + if (slice_config->dl->scheduler) + free(slice_config->dl->scheduler); + for (int i = 0; i < slice_config->dl->n_slices; i++) + if (slice_config->dl->slices[i]->scheduler) + free(slice_config->dl->slices[i]->scheduler); } - for (i = 0; i < m_ul; i++) { - flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]); + if (slice_config->ul) { + if (slice_config->ul->scheduler) + free(slice_config->ul->scheduler); + for (int i = 0; i < slice_config->ul->n_slices; i++) + if (slice_config->ul->slices[i]->scheduler) + free(slice_config->ul->slices[i]->scheduler); + } + + Protocol__FlexCellConfig helper; + helper.slice_config = slice_config; + flexran_agent_destroy_mac_slice_config(&helper); +} + +void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) { + if (!*slice_config) return; + /* just use the memory and set to NULL in original */ + Protocol__FlexSliceConfig *sc = *slice_config; + *slice_config = NULL; + + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + enum lfds700_misc_flag overwrite_occurred_flag; + + Protocol__FlexSliceConfig *overwritten_sc; + lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id], + NULL, + (void *)sc, + &overwrite_occurred_flag, + NULL, + (void **)&overwritten_sc, + &ls); + + if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) { + helper_destroy_mac_slice_config(overwritten_sc); + LOG_E(FLEXRAN_AGENT, "lost slice config: too many reconfigurations at once\n"); } } -void flexran_check_and_remove_slices(mid_t mod_id) -{ - Protocol__FlexDlSlice **dl = sc_update[mod_id]->dl; - Protocol__FlexDlSlice **dlreal = slice_config[mod_id]->dl; - int i = 0; - while (i < sc_update[mod_id]->n_dl) { - /* remove slices whose percentage is zero */ - if (dl[i]->percentage > 0) { - ++i; - continue; - } - if (flexran_remove_dl_slice(mod_id, i) < 1) { - LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n", - mod_id, i, dl[i]->id); - ++i; - continue; - } - LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n", - mod_id, i, dl[i]->id); - if (dl[i]->n_sorting > 0) free(dl[i]->sorting); - free(dl[i]->scheduler_name); - if (dlreal[i]->n_sorting > 0) { - dlreal[i]->n_sorting = 0; - free(dlreal[i]->sorting); - } - free(dlreal[i]->scheduler_name); - --sc_update[mod_id]->n_dl; - --slice_config[mod_id]->n_dl; - const size_t last = sc_update[mod_id]->n_dl; - /* we need to memcpy the higher slice to the position we just deleted */ - memcpy(dl[i], dl[last], sizeof(*dl[last])); - memset(dl[last], 0, sizeof(*dl[last])); - memcpy(dlreal[i], dlreal[last], sizeof(*dlreal[last])); - memset(dlreal[last], 0, sizeof(*dlreal[last])); - /* dont increase i but recheck the slice which has been copied to here */ - } - Protocol__FlexUlSlice **ul = sc_update[mod_id]->ul; - Protocol__FlexUlSlice **ulreal = slice_config[mod_id]->ul; - i = 0; - while (i < sc_update[mod_id]->n_ul) { - if (ul[i]->percentage > 0) { - ++i; - continue; - } - if (flexran_remove_ul_slice(mod_id, i) < 1) { - LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n", - mod_id, i, ul[i]->id); - ++i; - continue; - } - LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n", - mod_id, i, ul[i]->id); - free(ul[i]->scheduler_name); - free(ulreal[i]->scheduler_name); - --sc_update[mod_id]->n_ul; - --slice_config[mod_id]->n_ul; - const size_t last = sc_update[mod_id]->n_ul; - /* see DL remarks */ - memcpy(ul[i], ul[last], sizeof(*ul[last])); - memset(ul[last], 0, sizeof(*ul[last])); - memcpy(ulreal[i], ulreal[last], sizeof(*ulreal[last])); - memset(ulreal[last], 0, sizeof(*ulreal[last])); - /* dont increase i but recheck the slice which has been copied to here */ +void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config) { + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + enum lfds700_misc_flag overwrite_occurred_flag; + + Protocol__FlexUeConfig *overwritten_ue_config; + lfds700_ringbuffer_write(&ue_assoc_ringbuffer_state[mod_id], + NULL, + (void *) *ue_config, + &overwrite_occurred_flag, + NULL, + (void **)&overwritten_ue_config, + &ls); + + if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) { + free(overwritten_ue_config); + LOG_E(FLEXRAN_AGENT, "lost UE-slice association: too many UE-slice associations at once\n"); } } -void flexran_agent_slice_update(mid_t mod_id) -{ - int i; - int changes = 0; +void flexran_agent_slice_update(mid_t mod_id) { + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); - if (perform_slice_config_update_count <= 0) return; - perform_slice_config_update_count--; - - pthread_mutex_lock(&sc_update_mtx); - - if (!slice_config[mod_id]) { - /* if the configuration does not exist for agent, create from eNB structure - * and exit */ - flexran_create_config_structures(mod_id); - pthread_mutex_unlock(&sc_update_mtx); - return; + Protocol__FlexSliceConfig *sc = NULL; + struct lfds700_ringbuffer_state *state = &slice_config_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &sc, &ls) != 0) { + apply_update_dl_slice_config(mod_id, sc->dl); + apply_update_ul_slice_config(mod_id, sc->ul); + helper_destroy_mac_slice_config(sc); } - /********* read existing config *********/ - /* simply update slice_config all the time and write new config - * (apply_new_slice_dl_config() only updates if changes are necessary) */ - slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id); - slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id); - for (i = 0; i < slice_config[mod_id]->n_dl; i++) { - flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); + Protocol__FlexUeConfig *ue_config = NULL; + state = &ue_assoc_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &ue_config, &ls) != 0) { + apply_ue_slice_assoc_update(mod_id, ue_config); + free(ue_config); } - for (i = 0; i < slice_config[mod_id]->n_ul; i++) { - flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - } - - /********* write new config *********/ - /* check for removal (sc_update[X]->dl[Y].percentage == 0) - * and update sc_update & slice_config accordingly */ - flexran_check_and_remove_slices(mod_id); - - /* create new DL and UL slices if necessary */ - for (i = slice_config[mod_id]->n_dl; i < sc_update[mod_id]->n_dl; i++) { - flexran_create_dl_slice(mod_id, sc_update[mod_id]->dl[i]->id); - } - for (i = slice_config[mod_id]->n_ul; i < sc_update[mod_id]->n_ul; i++) { - flexran_create_ul_slice(mod_id, sc_update[mod_id]->ul[i]->id); - } - slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id); - slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id); - changes += apply_new_slice_config(mod_id, slice_config[mod_id], sc_update[mod_id]); - for (i = 0; i < slice_config[mod_id]->n_dl; i++) { - changes += apply_new_slice_dl_config(mod_id, - slice_config[mod_id]->dl[i], - sc_update[mod_id]->dl[i]); - flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - } - for (i = 0; i < slice_config[mod_id]->n_ul; i++) { - changes += apply_new_slice_ul_config(mod_id, - slice_config[mod_id]->ul[i], - sc_update[mod_id]->ul[i]); - flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - } - flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); - if (n_ue_slice_assoc_updates > 0) { - changes += apply_ue_slice_assoc_update(mod_id); - } - if (changes > 0) - LOG_I(FLEXRAN_AGENT, "[%d] slice configuration: applied %d changes\n", mod_id, changes); - - pthread_mutex_unlock(&sc_update_mtx); -} - -Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id) -{ - if (!slice_config[mod_id]) return NULL; - Protocol__FlexSliceConfig *config = NULL; - - pthread_mutex_lock(&sc_update_mtx); - config = flexran_agent_create_slice_config(slice_config[mod_id]->n_dl, - slice_config[mod_id]->n_ul); - if (!config) { - pthread_mutex_unlock(&sc_update_mtx); - return NULL; - } - config->has_intraslice_share_active = 1; - config->intraslice_share_active = slice_config[mod_id]->intraslice_share_active; - config->has_interslice_share_active = 1; - config->interslice_share_active = slice_config[mod_id]->interslice_share_active; - for (int i = 0; i < slice_config[mod_id]->n_dl; ++i) { - if (!config->dl[i]) continue; - config->dl[i]->has_id = 1; - config->dl[i]->id = slice_config[mod_id]->dl[i]->id; - config->dl[i]->has_label = 1; - config->dl[i]->label = slice_config[mod_id]->dl[i]->label; - config->dl[i]->has_percentage = 1; - config->dl[i]->percentage = slice_config[mod_id]->dl[i]->percentage; - config->dl[i]->has_isolation = 1; - config->dl[i]->isolation = slice_config[mod_id]->dl[i]->isolation; - config->dl[i]->has_priority = 1; - config->dl[i]->priority = slice_config[mod_id]->dl[i]->priority; - config->dl[i]->has_position_low = 1; - config->dl[i]->position_low = slice_config[mod_id]->dl[i]->position_low; - config->dl[i]->has_position_high = 1; - config->dl[i]->position_high = slice_config[mod_id]->dl[i]->position_high; - config->dl[i]->has_maxmcs = 1; - config->dl[i]->maxmcs = slice_config[mod_id]->dl[i]->maxmcs; - config->dl[i]->n_sorting = slice_config[mod_id]->dl[i]->n_sorting; - config->dl[i]->sorting = calloc(config->dl[i]->n_sorting, sizeof(Protocol__FlexDlSorting)); - if (!config->dl[i]->sorting) config->dl[i]->n_sorting = 0; - for (int j = 0; j < config->dl[i]->n_sorting; ++j) - config->dl[i]->sorting[j] = slice_config[mod_id]->dl[i]->sorting[j]; - config->dl[i]->has_accounting = 1; - config->dl[i]->accounting = slice_config[mod_id]->dl[i]->accounting; - config->dl[i]->scheduler_name = strdup(slice_config[mod_id]->dl[i]->scheduler_name); - } - for (int i = 0; i < slice_config[mod_id]->n_ul; ++i) { - if (!config->ul[i]) continue; - config->ul[i]->has_id = 1; - config->ul[i]->id = slice_config[mod_id]->ul[i]->id; - config->ul[i]->has_label = 1; - config->ul[i]->label = slice_config[mod_id]->ul[i]->label; - config->ul[i]->has_percentage = 1; - config->ul[i]->percentage = slice_config[mod_id]->ul[i]->percentage; - config->ul[i]->has_isolation = 1; - config->ul[i]->isolation = slice_config[mod_id]->ul[i]->isolation; - config->ul[i]->has_priority = 1; - config->ul[i]->priority = slice_config[mod_id]->ul[i]->priority; - config->ul[i]->has_first_rb = 1; - config->ul[i]->first_rb = slice_config[mod_id]->ul[i]->first_rb; - config->ul[i]->has_maxmcs = 1; - config->ul[i]->maxmcs = slice_config[mod_id]->ul[i]->maxmcs; - config->ul[i]->n_sorting = slice_config[mod_id]->ul[i]->n_sorting; - config->ul[i]->sorting = calloc(config->ul[i]->n_sorting, sizeof(Protocol__FlexUlSorting)); - if (!config->ul[i]->sorting) config->ul[i]->n_sorting = 0; - for (int j = 0; j < config->ul[i]->n_sorting; ++j) - config->ul[i]->sorting[j] = slice_config[mod_id]->ul[i]->sorting[j]; - config->ul[i]->has_accounting = 1; - config->ul[i]->accounting = slice_config[mod_id]->ul[i]->accounting; - config->ul[i]->scheduler_name = strdup(slice_config[mod_id]->ul[i]->scheduler_name); - } - - pthread_mutex_unlock(&sc_update_mtx); - return config; } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h index 2f9f99c740..5a8d4f31aa 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h @@ -115,7 +115,16 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id); /* Inform controller about possibility to update slice configuration */ void flexran_agent_slice_update(mid_t mod_id); -/* return a pointer to the current config */ -Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id); +/* marks slice_config so that it can be applied later. Takes ownership of the + * FlexSliceConfig message */ +void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice); + +/* inserts a new ue_config into the structure keeping ue to slice association + * updates and marks so it can be applied. Takes ownership of the FlexUeConfig message */ +void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config); + +/* free slice_config part of flexCellConfig, filled in + * flexran_agent_fill_mac_cell_config() */ +void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf); #endif 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 a85cbac543..93de0b11ec 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 @@ -33,14 +33,6 @@ #include "flexran_agent_mac_internal.h" #include "flexran_agent_mac_slice_verification.h" -/* from flexran_agent_mac.c */ -extern Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES]; -extern Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES]; -extern int perform_slice_config_update_count; -extern Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES]; -extern int n_ue_slice_assoc_updates; -extern pthread_mutex_t sc_update_mtx; - Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message, Protocol__FlexranMessage *old_message) { @@ -1033,724 +1025,166 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { } -Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) -{ - int i; - Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig)); - if (!fsc) return NULL; - protocol__flex_slice_config__init(fsc); - - /* say there are n_dl slices but reserve memory for up to MAX_NUM_SLICES so - * we don't need to reserve again later */ - fsc->n_dl = n_dl; - fsc->dl = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexDlSlice *)); - if (!fsc->dl) fsc->n_dl = 0; - for (i = 0; i < MAX_NUM_SLICES; i++) { - fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice)); - if (!fsc->dl[i]) continue; - protocol__flex_dl_slice__init(fsc->dl[i]); - } - - /* as above */ - fsc->n_ul = m_ul; - fsc->ul = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexUlSlice *)); - if (!fsc->ul) fsc->n_ul = 0; - for (i = 0; i < MAX_NUM_SLICES; i++) { - fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice)); - if (!fsc->ul[i]) continue; - protocol__flex_ul_slice__init(fsc->ul[i]); - } - return fsc; -} - -void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s) -{ - s->intraslice_share_active = flexran_get_intraslice_sharing_active(mod_id); - s->has_intraslice_share_active = 1; - s->interslice_share_active = flexran_get_interslice_sharing_active(mod_id); - s->has_interslice_share_active = 1; -} - -void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice) -{ - dl_slice->id = flexran_get_dl_slice_id(mod_id, slice_idx); - dl_slice->has_id = 1; - /* read label from corresponding sc_update entry or give default */ - dl_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB; - dl_slice->has_label = 1; - for (int i = 0; i < sc_update[mod_id]->n_dl; i++) { - if (sc_update[mod_id]->dl[i]->id == dl_slice->id - && sc_update[mod_id]->dl[i]->has_label) { - dl_slice->label = sc_update[mod_id]->dl[i]->label; - break; - } - } - dl_slice->percentage = flexran_get_dl_slice_percentage(mod_id, slice_idx); - dl_slice->has_percentage = 1; - dl_slice->isolation = flexran_get_dl_slice_isolation(mod_id, slice_idx); - dl_slice->has_isolation = 1; - dl_slice->priority = flexran_get_dl_slice_priority(mod_id, slice_idx); - dl_slice->has_priority = 1; - dl_slice->position_low = flexran_get_dl_slice_position_low(mod_id, slice_idx); - dl_slice->has_position_low = 1; - dl_slice->position_high = flexran_get_dl_slice_position_high(mod_id, slice_idx); - dl_slice->has_position_high = 1; - dl_slice->maxmcs = flexran_get_dl_slice_maxmcs(mod_id, slice_idx); - dl_slice->has_maxmcs = 1; - dl_slice->n_sorting = flexran_get_dl_slice_sorting(mod_id, slice_idx, &dl_slice->sorting); - if (dl_slice->n_sorting < 1) dl_slice->sorting = NULL; - dl_slice->accounting = flexran_get_dl_slice_accounting_policy(mod_id, slice_idx); - dl_slice->has_accounting = 1; - const char *s_name = flexran_get_dl_slice_scheduler(mod_id, slice_idx); - if (!dl_slice->scheduler_name - || strcmp(dl_slice->scheduler_name, s_name) != 0) { - dl_slice->scheduler_name = realloc(dl_slice->scheduler_name, strlen(s_name) + 1); - strcpy(dl_slice->scheduler_name, s_name); - } -} - -void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice) -{ - ul_slice->id = flexran_get_ul_slice_id(mod_id, slice_idx); - ul_slice->has_id = 1; - /* read label from corresponding sc_update entry or give default */ - ul_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB; - ul_slice->has_label = 1; - for (int i = 0; i < sc_update[mod_id]->n_ul; i++) { - if (sc_update[mod_id]->ul[i]->id == ul_slice->id - && sc_update[mod_id]->ul[i]->has_label) { - ul_slice->label = sc_update[mod_id]->ul[i]->label; - break; - } - } - ul_slice->percentage = flexran_get_ul_slice_percentage(mod_id, slice_idx); - ul_slice->has_percentage = 1; - /*ul_slice->isolation = flexran_get_ul_slice_isolation(mod_id, slice_idx);*/ - ul_slice->has_isolation = 0; - /*ul_slice->priority = flexran_get_ul_slice_priority(mod_id, slice_idx);*/ - ul_slice->has_priority = 0; - ul_slice->first_rb = flexran_get_ul_slice_first_rb(mod_id, slice_idx); - ul_slice->has_first_rb = 1; - /*ul_slice-> = flexran_get_ul_slice_length_rb(mod_id, slice_idx); - ul_slice->has_length_rb = 0;*/ - ul_slice->maxmcs = flexran_get_ul_slice_maxmcs(mod_id, slice_idx); - ul_slice->has_maxmcs = 1; - ul_slice->n_sorting = 0; - /*if (ul_slice->sorting) { - free(ul_slice->sorting); - ul_slice->sorting = NULL; - } - ul_slice->n_sorting = flexran_get_ul_slice_sorting(mod_id, slice_idx, &ul_slice->sorting); - if (ul_slice->n_sorting < 1) ul_slice->sorting = NULL;*/ - /*ul_slice->accounting = flexran_get_ul_slice_accounting_policy(mod_id, slice_idx);*/ - ul_slice->has_accounting = 0; - const char *s_name = flexran_get_ul_slice_scheduler(mod_id, slice_idx); - if (!ul_slice->scheduler_name - || strcmp(ul_slice->scheduler_name, s_name) != 0) { - ul_slice->scheduler_name = realloc(ul_slice->scheduler_name, strlen(s_name) + 1); - strcpy(ul_slice->scheduler_name, s_name); - } -} - -int check_dl_sorting_update(Protocol__FlexDlSlice *old, Protocol__FlexDlSlice *new) -{ - /* sorting_update => true when old->n_sorting == 0 or different numbers of - * elements; otherwise will check * element-wise */ - int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting); - for (int i = 0; i < old->n_sorting && !sorting_update; ++i) { - sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]); - } - return sorting_update; -} - -int check_ul_sorting_update(Protocol__FlexUlSlice *old, Protocol__FlexUlSlice *new) -{ - /* sorting_update => true when old->n_sorting == 0 or different numbers of - * elements; otherwise will check * element-wise */ - int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting); - for (int i = 0; i < old->n_sorting && !sorting_update; ++i) { - sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]); - } - return sorting_update; -} - -void overwrite_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *exist, Protocol__FlexSliceConfig *update) -{ - if (update->has_intraslice_share_active - && exist->intraslice_share_active != update->intraslice_share_active) { - LOG_I(FLEXRAN_AGENT, "[%d] update intraslice_share_active: %d -> %d\n", - mod_id, exist->intraslice_share_active, update->intraslice_share_active); - exist->intraslice_share_active = update->intraslice_share_active; - exist->has_intraslice_share_active = 1; - } - if (update->has_interslice_share_active - && exist->interslice_share_active != update->interslice_share_active) { - LOG_I(FLEXRAN_AGENT, "[%d] update interslice_share_active: %d -> %d\n", - mod_id, exist->interslice_share_active, update->interslice_share_active); - exist->interslice_share_active = update->interslice_share_active; - exist->has_interslice_share_active = 1; - } -} - -void overwrite_slice_config_dl(mid_t mod_id, Protocol__FlexDlSlice *exist, Protocol__FlexDlSlice *update) -{ - if (update->label != exist->label) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update label: %d -> %d\n", - mod_id, update->id, exist->label, update->label); - exist->label = update->label; - exist->has_label = 1; - } - if (update->percentage != exist->percentage) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update percentage: %d -> %d\n", - mod_id, update->id, exist->percentage, update->percentage); - exist->percentage = update->percentage; - exist->has_percentage = 1; - } - if (update->isolation != exist->isolation) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update isolation: %d -> %d\n", - mod_id, update->id, exist->isolation, update->isolation); - exist->isolation = update->isolation; - exist->has_isolation = 1; - } - if (update->priority != exist->priority) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update priority: %d -> %d\n", - mod_id, update->id, exist->priority, update->priority); - exist->priority = update->priority; - exist->has_priority = 1; - } - if (update->position_low != exist->position_low) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_low: %d -> %d\n", - mod_id, update->id, exist->position_low, update->position_low); - exist->position_low = update->position_low; - exist->has_position_low = 1; - } - if (update->position_high != exist->position_high) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_high: %d -> %d\n", - mod_id, update->id, exist->position_high, update->position_high); - exist->position_high = update->position_high; - exist->has_position_high = 1; - } - if (update->maxmcs != exist->maxmcs) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update maxmcs: %d -> %d\n", - mod_id, update->id, exist->maxmcs, update->maxmcs); - exist->maxmcs = update->maxmcs; - exist->has_maxmcs = 1; - } - if (check_dl_sorting_update(exist, update)) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update sorting array\n", mod_id, update->id); - if (exist->n_sorting != update->n_sorting) { - exist->n_sorting = update->n_sorting; - exist->sorting = realloc(exist->sorting, exist->n_sorting * sizeof(Protocol__FlexDlSorting)); - if (!exist->sorting) exist->n_sorting = 0; - } - for (int i = 0; i < exist->n_sorting; i++) - exist->sorting[i] = update->sorting[i]; - } - if (update->accounting != exist->accounting) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update accounting: %d -> %d\n", - mod_id, update->id, exist->accounting, update->accounting); - exist->accounting = update->accounting; - exist->has_accounting = 1; - } - if (!exist->scheduler_name - || strcmp(update->scheduler_name, exist->scheduler_name) != 0) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update scheduler: %s -> %s\n", - mod_id, update->id, exist->scheduler_name, update->scheduler_name); - if (exist->scheduler_name) free(exist->scheduler_name); - exist->scheduler_name = strdup(update->scheduler_name); - } -} - -void overwrite_slice_config_ul(mid_t mod_id, Protocol__FlexUlSlice *exist, Protocol__FlexUlSlice *update) -{ - if (update->label != exist->label) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update label: %d -> %d\n", - mod_id, update->id, exist->label, update->label); - exist->label = update->label; - exist->has_label = 1; - } - if (update->percentage != exist->percentage) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update percentage: %d -> %d\n", - mod_id, update->id, exist->percentage, update->percentage); - exist->percentage = update->percentage; - exist->has_percentage = 1; - } - if (update->isolation != exist->isolation) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update isolation: %d -> %d\n", - mod_id, update->id, exist->isolation, update->isolation); - exist->isolation = update->isolation; - exist->has_isolation = 1; - } - if (update->priority != exist->priority) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update priority: %d -> %d\n", - mod_id, update->id, exist->priority, update->priority); - exist->priority = update->priority; - exist->has_priority = 1; - } - if (update->first_rb != exist->first_rb) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update first_rb: %d -> %d\n", - mod_id, update->id, exist->first_rb, update->first_rb); - exist->first_rb = update ->first_rb; - exist->has_first_rb = 1; - } - /*if (update->lenght_rb != exist->lenght_rb) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update lenght_rb: %d -> %d\n", - mod_id, update->id, exist->lenght_rb, update->lenght_rb); - exist->lenght_rb = update->lenght_rb; - }*/ - if (update->maxmcs != exist->maxmcs) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update maxmcs: %d -> %d\n", - mod_id, update->id, exist->maxmcs, update->maxmcs); - exist->maxmcs = update->maxmcs; - exist->has_maxmcs = 1; - } - /* TODO - int sorting_update = 0; - int n = min(exist->n_sorting, update->n_sorting); - int i = 0; - while (i < n && !sorting_update) { - sorting_update = sorting_update || (update->sorting[i] != exist->sorting[i]); - i++; - } - if (sorting_update) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update sorting array\n", update->id, mod_id); - if (exist->n_sorting != update->n_sorting) - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] only writing %d elements\n", - mod_id, update->id, n); - for (i = 0; i < n; i++) - exist->sorting[i] = update->sorting[i]; - } - */ - if (update->accounting != exist->accounting) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update accounting: %d -> %d\n", - mod_id, update->id, exist->accounting, update->accounting); - exist->accounting = update->accounting; - exist->has_accounting = 1; - } - if (!exist->scheduler_name - || strcmp(update->scheduler_name, exist->scheduler_name) != 0) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update scheduler: %s -> %s\n", - mod_id, update->id, exist->scheduler_name, update->scheduler_name); - if (exist->scheduler_name) free(exist->scheduler_name); - exist->scheduler_name = strdup(update->scheduler_name); - } -} - -void fill_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *s, Protocol__FlexDlSlice *from) -{ - /* function fills slice with information from another slice or with default - * values (currently slice 0) if from is NULL */ - /* TODO fill the slice depending on the chosen label */ - if (!s->has_label) { - s->has_label = 1; - s->label = from ? from->label : sc_update[mod_id]->dl[0]->label; - } - if (!s->has_percentage) { - s->has_percentage = 1; - s->percentage = from ? from->percentage : sc_update[mod_id]->dl[0]->percentage; - } - if (!s->has_isolation) { - s->has_isolation = 1; - s->isolation = from ? from->isolation : sc_update[mod_id]->dl[0]->isolation; - } - if (!s->has_priority) { - s->has_priority = 1; - s->priority = from ? from->priority : sc_update[mod_id]->dl[0]->priority; - } - if (!s->has_position_low) { - s->has_position_low = 1; - s->position_low = from ? from->position_low : sc_update[mod_id]->dl[0]->position_low; - } - if (!s->has_position_high) { - s->has_position_high = 1; - s->position_high = from ? from->position_high : sc_update[mod_id]->dl[0]->position_high; - } - if (!s->has_maxmcs) { - s->has_maxmcs = 1; - s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->dl[0]->maxmcs; - } - if (s->n_sorting == 0) { - s->n_sorting = from ? from->n_sorting : sc_update[mod_id]->dl[0]->n_sorting; - s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexDlSorting)); - if (!s->sorting) s->n_sorting = 0; - for (int i = 0; i < s->n_sorting; ++i) - s->sorting[i] = from ? from->sorting[i] : sc_update[0]->dl[0]->sorting[i]; - } - if (!s->has_accounting) { - s->accounting = from ? from->accounting : sc_update[mod_id]->dl[0]->accounting; - } - if (!s->scheduler_name) { - s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->dl[0]->scheduler_name); - } -} - -Protocol__FlexDlSlice *get_existing_dl_slice(mid_t mod_id, int id) -{ - for (int i = 0; i < sc_update[mod_id]->n_dl; ++i) { - if (id == sc_update[mod_id]->dl[i]->id) { - return sc_update[mod_id]->dl[i]; - } - } - return NULL; -} - -Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id) -{ - LOG_I(FLEXRAN_AGENT, - "[%d] Creating DL slice with ID %d, taking default values from DL slice 0\n", - mod_id, id); - Protocol__FlexDlSlice *to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl]; - sc_update[mod_id]->n_dl++; - AssertFatal(sc_update[mod_id]->n_dl <= MAX_NUM_SLICES, - "cannot create more than MAX_NUM_SLICES\n"); - to->id = id; - return to; -} - -void fill_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *s, Protocol__FlexUlSlice *from) -{ - /* function fills slice with information from another slice or with default - * values (currently slice 0) if from is NULL */ - /* TODO fill the slice depending on the chosen label */ - if (!s->has_label) { - s->has_label = 1; - s->label = from ? from->label : sc_update[mod_id]->ul[0]->label; - } - if (!s->has_percentage) { - s->has_percentage = 1; - s->percentage = from ? from->percentage : sc_update[mod_id]->ul[0]->percentage; - } - if (!s->has_isolation) { - s->has_isolation = 1; - s->isolation = from ? from->isolation : sc_update[mod_id]->ul[0]->isolation; - } - if (!s->has_priority) { - s->has_priority = 1; - s->priority = from ? from->priority : sc_update[mod_id]->ul[0]->priority; - } - if (!s->has_first_rb) { - s->has_first_rb = 1; - s->first_rb = from ? from->first_rb : sc_update[mod_id]->ul[0]->first_rb; - } - if (!s->has_maxmcs) { - s->has_maxmcs = 1; - s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->ul[0]->maxmcs; - } - if (s->n_sorting == 0) { - s->n_sorting = from ? from->n_sorting : sc_update[0]->ul[0]->n_sorting; - s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexUlSorting)); - if (!s->sorting) s->n_sorting = 0; - for (int i = 0; i < s->n_sorting; ++i) - s->sorting[i] = from ? from->sorting[i] : sc_update[0]->ul[0]->sorting[i]; - } - if (!s->has_accounting) { - s->accounting = from ? from->accounting : sc_update[0]->ul[0]->accounting; - } - if (!s->scheduler_name) { - s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->ul[0]->scheduler_name); - } -} - -Protocol__FlexUlSlice *get_existing_ul_slice(mid_t mod_id, int id) -{ - for (int i = 0; i < sc_update[mod_id]->n_ul; ++i) { - if (id == sc_update[mod_id]->ul[i]->id) { - return sc_update[mod_id]->ul[i]; - } - } - return NULL; -} - -Protocol__FlexUlSlice *create_new_ul_slice(mid_t mod_id, int id) -{ - LOG_I(FLEXRAN_AGENT, - "[%d] Creating UL slice with ID %d, taking default values from UL slice 0\n", - mod_id, id); - Protocol__FlexUlSlice *to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul]; - sc_update[mod_id]->n_ul++; - AssertFatal(sc_update[mod_id]->n_ul <= MAX_NUM_SLICES, - "cannot create more than MAX_NUM_SLICES\n"); - to->id = id; - return to; -} - -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *sup) -{ - int verified = 1; - if (!sc_update[mod_id]) { - LOG_E(FLEXRAN_AGENT, "Can not update slice policy (no existing slice profile)\n"); - return; - } - - pthread_mutex_lock(&sc_update_mtx); - /* no need for tests in the current state as there are only two protobuf - * bools for intra-/interslice sharing. The function applies new values if - * applicable */ - overwrite_slice_config(mod_id, sc_update[mod_id], sup); - - if (sup->n_dl == 0) { - LOG_I(FLEXRAN_AGENT, "[%d] no DL slice configuration in flex_slice_config message\n", mod_id); +void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) { + if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET + && !s->label && !s->scheduler) { + LOG_I(FLEXRAN_AGENT, "remove DL slice ID %d\n", s->id); + const int rc = flexran_remove_dl_slice(mod_id, s); + if (!rc) + LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); } else { - /* verify slice parameters */ - for (int i = 0; i < sup->n_dl; i++) { - if (!sup->dl[i]->has_id) { - verified = 0; - break; - } - Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id); - /* fill up so that the slice is complete. This way, we don't need to - * worry about it later */ - fill_dl_slice(mod_id, sup->dl[i], dls); - verified = verified && flexran_verify_dl_slice(mod_id, sup->dl[i]); - if (!verified) break; - } - - /* verify group-based parameters (e.g. sum percentage should not exceed - * 100%). Can be used to perform admission control */ - verified = verified && flexran_verify_group_dl_slices(mod_id, - sc_update[mod_id]->dl, sc_update[mod_id]->n_dl, sup->dl, sup->n_dl); - - if (verified) { - for (int i = 0; i < sup->n_dl; i++) { - /* if all verifications were successful, get existing slice for ID or - * create new one and overwrite with the update */ - Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id); - if (!dls) dls = create_new_dl_slice(mod_id, sup->dl[i]->id); - overwrite_slice_config_dl(mod_id, dls, sup->dl[i]); - } - } else { - LOG_E(FLEXRAN_AGENT, "[%d] DL slice verification failed, refusing application\n", mod_id); - } + LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id); + const int rc = flexran_create_dl_slice(mod_id, s); + if (rc < 0) + LOG_W(FLEXRAN_AGENT, + "error while update slice ID %d: flexran_create_dl_slice() -> %d\n", + s->id, rc); } +} - verified = 1; - if (sup->n_ul == 0) { - LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_id); +void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) { + if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET + && !s->label && !s->scheduler) { + LOG_I(FLEXRAN_AGENT, "remove UL slice ID %d\n", s->id); + const int rc = flexran_remove_ul_slice(mod_id, s); + if (!rc) + LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); } else { - /* verify slice parameters */ - for (int i = 0; i < sup->n_ul; i++) { - if (!sup->ul[i]->has_id) { - verified = 0; - break; - } - Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id); - /* fill up so that the slice is complete. This way, we don't need to - * worry about it later */ - fill_ul_slice(mod_id, sup->ul[i], uls); - verified = verified && flexran_verify_ul_slice(mod_id, sup->ul[i]); - if (!verified) break; - } - - /* verify group-based parameters (e.g. sum percentage should not exceed - * 100%). Can be used to perform admission control */ - verified = verified && flexran_verify_group_ul_slices(mod_id, - sc_update[mod_id]->ul, sc_update[mod_id]->n_ul, sup->ul, sup->n_ul); - - if (verified) { - for (int i = 0; i < sup->n_ul; i++) { - /* if all verifications were successful, get existing slice for ID or - * create new one and overwrite with the update */ - Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id); - if (!uls) uls = create_new_ul_slice(mod_id, sup->ul[i]->id); - overwrite_slice_config_ul(mod_id, uls, sup->ul[i]); - } - } else { - LOG_E(FLEXRAN_AGENT, "[%d] UL slice verification failed, refusing application\n", mod_id); - } + LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id); + const int rc = flexran_create_ul_slice(mod_id, s); + if (rc < 0) + LOG_W(FLEXRAN_AGENT, + "error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n", + s->id, rc); } - pthread_mutex_unlock(&sc_update_mtx); - - perform_slice_config_update_count = 1; } -int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news) -{ - /* not setting the old configuration is intentional, as it will be picked up - * later when reading the configuration. There is thus a direct feedback - * whether it has been set. */ - int changes = 0; - if (olds->intraslice_share_active != news->intraslice_share_active) { - flexran_set_intraslice_sharing_active(mod_id, news->intraslice_share_active); - changes++; - } - if (olds->interslice_share_active != news->interslice_share_active) { - flexran_set_interslice_sharing_active(mod_id, news->interslice_share_active); - changes++; - } - return changes; -} - -int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc) -{ - /* not setting the old configuration is intentional, as it will be picked up - * later when reading the configuration. There is thus a direct feedback - * whether it has been set. */ - int changes = 0; - int slice_idx = flexran_find_dl_slice(mod_id, newc->id); - if (slice_idx < 0) { - LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id); - return 0; - } - if (oldc->percentage != newc->percentage) { - flexran_set_dl_slice_percentage(mod_id, slice_idx, newc->percentage); - changes++; - } - if (oldc->isolation != newc->isolation) { - flexran_set_dl_slice_isolation(mod_id, slice_idx, newc->isolation); - changes++; - } - if (oldc->priority != newc->priority) { - flexran_set_dl_slice_priority(mod_id, slice_idx, newc->priority); - changes++; - } - if (oldc->position_low != newc->position_low) { - flexran_set_dl_slice_position_low(mod_id, slice_idx, newc->position_low); - changes++; - } - if (oldc->position_high != newc->position_high) { - flexran_set_dl_slice_position_high(mod_id, slice_idx, newc->position_high); - changes++; - } - if (oldc->maxmcs != newc->maxmcs) { - flexran_set_dl_slice_maxmcs(mod_id, slice_idx, newc->maxmcs); - changes++; - } - if (check_dl_sorting_update(oldc, newc)) { - flexran_set_dl_slice_sorting(mod_id, slice_idx, newc->sorting, newc->n_sorting); - changes++; - } - if (oldc->accounting != newc->accounting) { - flexran_set_dl_slice_accounting_policy(mod_id, slice_idx, newc->accounting); - changes++; - } - if (!oldc->scheduler_name - || strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) { - int ret = flexran_set_dl_slice_scheduler(mod_id, slice_idx, newc->scheduler_name); - AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n", - newc->id, slice_idx); - changes++; - } - return changes; -} - -int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc) -{ - /* not setting the old configuration is intentional, as it will be picked up - * later when reading the configuration. There is thus a direct feedback - * whether it has been set. */ - int changes = 0; - int slice_idx = flexran_find_ul_slice(mod_id, newc->id); - if (slice_idx < 0) { - LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id); - return 0; - } - if (oldc->percentage != newc->percentage) { - flexran_set_ul_slice_percentage(mod_id, slice_idx, newc->percentage); - changes++; - } - if (oldc->isolation != newc->isolation) { - /*flexran_set_ul_slice_isolation(mod_id, slice_idx, newc->isolation); - *changes++;*/ - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting isolation is not supported\n", - mod_id, newc->id); - } - if (oldc->priority != newc->priority) { - /*flexran_set_ul_slice_priority(mod_id, slice_idx, newc->priority); - *changes++;*/ - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the priority is not supported\n", - mod_id, newc->id); - } - if (oldc->first_rb != newc->first_rb) { - flexran_set_ul_slice_first_rb(mod_id, slice_idx, newc->first_rb); - changes++; - } - /*if (oldc->length_rb != newc->length_rb) { - flexran_set_ul_slice_length_rb(mod_id, slice_idx, newc->length_rb); - changes++; - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting length_rb is not supported\n", - mod_id, newc->id); - }*/ - if (oldc->maxmcs != newc->maxmcs) { - flexran_set_ul_slice_maxmcs(mod_id, slice_idx, newc->maxmcs); - changes++; - } - /*if (check_ul_sorting_update(oldc, newc)) { - flexran_set_ul_slice_sorting(mod_id, slice_idx, newc->sorting, n); - changes++; - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the sorting is not supported\n", - mod_id, newc->id); - }*/ - if (oldc->accounting != newc->accounting) { - /*flexran_set_ul_slice_accounting_policy(mod_id, slice_idx, newc->accounting); - *changes++;*/ - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the accounting is not supported\n", - mod_id, newc->id); - } - if (!oldc->scheduler_name - || strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) { - int ret = flexran_set_ul_slice_scheduler(mod_id, slice_idx, newc->scheduler_name); - AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n", - newc->id, slice_idx); - changes++; - } - return changes; -} - -void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) -{ - if (n_ue_slice_assoc_updates == MAX_NUM_SLICES) { - LOG_E(FLEXRAN_AGENT, - "[%d] can not handle flex_ue_config message, buffer is full; try again later\n", - mod_id); +void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *dl) { + if (!dl) return; + + Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id); + if (dl->has_algorithm && dl_algo != dl->algorithm) { + LOG_I(FLEXRAN_AGENT, "loading new DL slice algorithm %d\n", dl->algorithm); + dl_algo = dl->algorithm; + flexran_set_dl_slice_algo(mod_id, dl_algo); } + + /* first update existing slices, then create new. Thus, we go through the + * list twice. First round, if a slice exists, handle and mark as such. Then, + * apply all others in the second round */ + if (dl->n_slices > 0) { + if (dl_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n"); + return; + } + int handled_dl[dl->n_slices]; + for (int i = 0; i < dl->n_slices; ++i) { + if (flexran_find_dl_slice(mod_id, dl->slices[i]->id) < 0) { + handled_dl[i] = 0; + continue; + } + update_or_remove_dl(mod_id, dl->slices[i]); + handled_dl[i] = 1; + } + for (int i = 0; i < dl->n_slices; ++i) { + if (handled_dl[i]) + continue; + update_or_remove_dl(mod_id, dl->slices[i]); + } + } + + if (dl->scheduler) { + if (dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); + return; + } + LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler); + const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, + "error while updating scheduling algorithm: " + "flexran_update_dl_sched_algo() -> %d)\n", + rc); + return; + } + } +} + +void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *ul) { + if (!ul) + return; + + Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id); + if (ul->has_algorithm && ul_algo != ul->algorithm) { + LOG_I(FLEXRAN_AGENT, "loading new UL slice algorithm %d\n", ul->algorithm); + ul_algo = ul->algorithm; + flexran_set_ul_slice_algo(mod_id, ul_algo); + } + if (ul->n_slices > 0) { + if (ul_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n"); + return; + } + int handled_ul[ul->n_slices]; + for (int i = 0; i < ul->n_slices; ++i) { + if (flexran_find_ul_slice(mod_id, ul->slices[i]->id) < 0) { + handled_ul[i] = 0; + continue; + } + update_or_remove_ul(mod_id, ul->slices[i]); + handled_ul[i] = 1; + } + for (int i = 0; i < ul->n_slices; ++i) { + if (handled_ul[i]) + continue; + update_or_remove_ul(mod_id, ul->slices[i]); + } + } + + if (ul->scheduler) { + if (ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); + return; + } + LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler); + const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, + "error while updating scheduling algorithm: " + "flexran_update_dl_sched_algo() -> %d)\n", + rc); + return; + } + } +} + +int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) +{ if (!ue_config->has_rnti) { LOG_E(FLEXRAN_AGENT, "[%d] cannot update UE to slice association, no RNTI in flex_ue_config message\n", mod_id); - return; + return 0; } - if (ue_config->has_dl_slice_id) - LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to DL slice ID %d\n", - mod_id, ue_config->rnti, ue_config->dl_slice_id); - if (ue_config->has_ul_slice_id) - LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to UL slice ID %d\n", - mod_id, ue_config->rnti, ue_config->ul_slice_id); - ue_slice_assoc_update[n_ue_slice_assoc_updates++] = ue_config; - perform_slice_config_update_count = 2; -} - -int apply_ue_slice_assoc_update(mid_t mod_id) -{ - int i; - int changes = 0; - for (i = 0; i < n_ue_slice_assoc_updates; i++) { - int ue_id = find_UE_id(mod_id, ue_slice_assoc_update[i]->rnti); - if (ue_id < 0 || ue_id > MAX_MOBILES_PER_ENB){ - LOG_E(FLEXRAN_AGENT,"UE_id %d is wrong!!\n",ue_id); - continue; - } - if (ue_slice_assoc_update[i]->has_dl_slice_id) { - int slice_idx = flexran_find_dl_slice(mod_id, ue_slice_assoc_update[i]->dl_slice_id); - if (flexran_dl_slice_exists(mod_id, slice_idx)) { - flexran_set_ue_dl_slice_idx(mod_id, ue_id, slice_idx); - changes++; - } else { - LOG_W(FLEXRAN_AGENT, "[%d] DL slice %d does not exist, refusing change\n", - mod_id, ue_slice_assoc_update[i]->dl_slice_id); - } - } - if (ue_slice_assoc_update[i]->has_ul_slice_id) { - int slice_idx = flexran_find_ul_slice(mod_id, ue_slice_assoc_update[i]->ul_slice_id); - if (flexran_ul_slice_exists(mod_id, slice_idx)) { - flexran_set_ue_ul_slice_idx(mod_id, ue_id, slice_idx); - changes++; - } else { - LOG_W(FLEXRAN_AGENT, "[%d] UL slice %d does not exist, refusing change\n", - mod_id, ue_slice_assoc_update[i]->ul_slice_id); - } + int UE_id = flexran_get_mac_ue_id_rnti(mod_id, ue_config->rnti); + if (ue_config->has_dl_slice_id) { + if (flexran_get_dl_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "no DL slice algorithm loaded\n"); + } else { + LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to DL slice ID %d\n", + mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->dl_slice_id); + flexran_set_ue_dl_slice_id(mod_id, UE_id, ue_config->dl_slice_id); } } - n_ue_slice_assoc_updates = 0; - return changes; + if (ue_config->has_ul_slice_id) { + if (flexran_get_ul_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "no UL slice algorithm loaded\n"); + } else { + LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to UL slice ID %d\n", + mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->ul_slice_id); + flexran_set_ue_ul_slice_id(mod_id, UE_id, ue_config->ul_slice_id); + } + } + return 0; } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h index 957fe6065e..9db5d61a11 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h @@ -103,43 +103,11 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name); /*** Functions for handling a slice config ***/ -/* allocate memory for a Protocol__FlexSliceConfig structure with n_dl DL slice - * configs and m_ul UL slice configs */ -Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul); - -/* read the general slice parameters via RAN into the given - * Protocol__FlexSliceConfig struct */ -void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s); - -/* read the DL slice config via the RAN into a given Protocol__FlexDlSlice - * struct */ -void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice); - -/* read the UL slice config via the RAN into a given Protocol__FlexUlSlice - * struct */ -void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice); - -/* reads content of slice over the sc_update structure, so that it can be - * applied later by performing a diff between slice_config and sc_update */ -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice); - -/* apply generic slice parameters (e.g. intra-/interslice sharing activated or - * not) if there are changes. Returns the number of changed parameters. */ -int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news); - -/* apply new configuration of slice in DL if there are changes between the - * parameters. Returns the number of changed parameters. */ -int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc); - -/* apply new configuration of slice in UL if there are changes between the - * parameters. Returns the number of changed parameters. */ -int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc); - -/* inserts a new ue_config into the structure keeping ue to slice association - * updates and marks so it can be applied */ -void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config); +/* Prepare the application of a slicing config */ +void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice); +void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice); /* apply a new association between a UE and a slice (both DL and UL) */ -int apply_ue_slice_assoc_update(mid_t mod_id); +int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config); #endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/ diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c index 67329e91be..6e54e155c2 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c @@ -28,346 +28,3 @@ #include "flexran_agent_mac_slice_verification.h" - -/* overlap check for UL slices, helper type */ -struct sregion_s { - int start; - int length; -}; - -/* forward declaration of locally-used verification functions */ -int flexran_dl_slice_verify_pct(int pct); -int flexran_dl_slice_verify_priority(int prio); -int flexran_dl_slice_verify_position(int pos_low, int pos_high); -int flexran_dl_slice_verify_maxmcs(int maxmcs); -int flexran_ul_slice_verify_pct(int pct); -int flexran_ul_slice_verify_priority(int prio); -int flexran_ul_slice_verify_first_rb(int first_rb); -int flexran_ul_slice_verify_maxmcs(int maxmcs); -int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n); - -int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls) -{ - /* check mandatory parameters */ - if (!dls->has_id) { - LOG_E(FLEXRAN_AGENT, "[%d] Incoming DL slice configuration has no ID\n", mod_id); - return 0; - } - - /* verify parameters individualy */ - /* label is enum */ - if (!flexran_dl_slice_verify_pct(dls->percentage)) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice percentage (%d)\n", - mod_id, dls->id, dls->percentage); - return 0; - } - /* isolation is a protobuf bool */ - if (!flexran_dl_slice_verify_priority(dls->priority)) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice priority (%d)\n", - mod_id, dls->id, dls->priority); - return 0; - } - if (!flexran_dl_slice_verify_position(dls->position_low, dls->position_high)) { - LOG_E(FLEXRAN_AGENT, - "[%d][DL slice %d] illegal DL slice position low (%d) and/or high (%d)\n", - mod_id, dls->id, dls->position_low, dls->position_high); - return 0; - } - if (!flexran_dl_slice_verify_maxmcs(dls->maxmcs)) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice max mcs %d\n", - mod_id, dls->id, dls->maxmcs); - return 0; - } - if (dls->n_sorting == 0) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting in DL slice\n", - mod_id, dls->id); - return 0; - } - if (!dls->sorting) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting found in DL slice\n", - mod_id, dls->id); - return 0; - } - /* sorting is an enum */ - /* accounting is an enum */ - if (!dls->scheduler_name) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no scheduler name found\n", - mod_id, dls->id); - return 0; - } - if (strcmp(dls->scheduler_name, "schedule_ue_spec") != 0) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] setting the scheduler to something " - "different than schedule_ue_spec is currently not allowed\n", - mod_id, dls->id); - return 0; - } - - return 1; -} - -int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing, - int n_ex, Protocol__FlexDlSlice **update, int n_up) -{ - int i, j, n; - int pct, pct_orig; - /* for every update, array points to existing slice, or NULL if update - * creates new slice */ - Protocol__FlexDlSlice *s[n_up]; - for (i = 0; i < n_up; i++) { - s[i] = NULL; - for (j = 0; j < n_ex; j++) { - if (existing[j]->id == update[i]->id) - s[i] = existing[j]; - } - } - - /* check that number of created and number of added slices in total matches - * [1,10] */ - n = n_ex; - for (i = 0; i < n_up; i++) { - /* new slice */ - if (!s[i]) n += 1; - /* slice will be deleted */ - else if (s[i]->percentage == 0) n -= 1; - /* else "only" an update */ - } - - if (n < 1 || n > MAX_NUM_SLICES) { - LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting DL slices (%d -> %d)\n", - mod_id, n_ex, n); - return 0; - } - - /* check that the sum of all slices percentages (including removed/added - * slices) matches [1,100] */ - pct = 0; - for (i = 0; i < n_ex; i++) { - pct += existing[i]->percentage; - } - pct_orig = pct; - for (i = 0; i < n_up; i++) { - /* if there is an existing slice, subtract its percentage and add the - * update's percentage */ - if (s[i]) - pct -= s[i]->percentage; - pct += update[i]->percentage; - } - if (pct < 1 || pct > 100) { - LOG_E(FLEXRAN_AGENT, - "[%d] invalid total RB share for DL slices (%d%% -> %d%%)\n", - mod_id, pct_orig, pct); - return 0; - } - - return 1; -} - -int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls) -{ - /* check mandatory parameters */ - if (!uls->has_id) { - LOG_E(FLEXRAN_AGENT, "[%d] Incoming UL slice configuration has no ID\n", mod_id); - return 0; - } - - /* verify parameters individually */ - /* label is enum */ - if (!flexran_ul_slice_verify_pct(uls->percentage)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n", - mod_id, uls->id, uls->percentage); - return 0; - } - /* isolation is a protobuf bool */ - if (!flexran_ul_slice_verify_priority(uls->priority)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n", - mod_id, uls->id, uls->priority); - return 0; - } - if (!flexran_ul_slice_verify_first_rb(uls->first_rb)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice first RB (%d)\n", - mod_id, uls->id, uls->first_rb); - return 0; - } - if (!flexran_ul_slice_verify_maxmcs(uls->maxmcs)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice max mcs (%d)\n", - mod_id, uls->id, uls->maxmcs); - return 0; - } - /* TODO - if (uls->n_sorting == 0) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting in UL slice\n", - mod_id, uls->id); - return 0; - } - if (!uls->sorting) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting found in UL slice\n", - mod_id, uls->id); - return 0; - } - */ - /* sorting is an enum */ - /* accounting is an enum */ - if (!uls->scheduler_name) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no scheduler name found\n", - mod_id, uls->id); - return 0; - } - if (strcmp(uls->scheduler_name, "schedule_ulsch_rnti") != 0) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] setting the scheduler to something " - "different than schedule_ulsch_rnti is currently not allowed\n", - mod_id, uls->id); - return 0; - } - - return 1; -} - -int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing, - int n_ex, Protocol__FlexUlSlice **update, int n_up) -{ - int i, j, n; - int pct, pct_orig; - /* for every update, array "s" points to existing slice, or NULL if update - * creates new slice; array "offs" gives the offset of this slice */ - Protocol__FlexUlSlice *s[n_up]; - int offs[n_up]; - for (i = 0; i < n_up; i++) { - s[i] = NULL; - offs[i] = 0; - for (j = 0; j < n_ex; j++) { - if (existing[j]->id == update[i]->id) { - s[i] = existing[j]; - offs[i] = j; - } - } - } - - /* check that number of created and number of added slices in total matches - * [1,10] */ - n = n_ex; - for (i = 0; i < n_up; i++) { - /* new slice */ - if (!s[i]) n += 1; - /* slice will be deleted */ - else if (s[i]->percentage == 0) n -= 1; - /* else "only" an update */ - } - - if (n < 1 || n > MAX_NUM_SLICES) { - LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting UL slices (%d -> %d)\n", - mod_id, n_ex, n); - return 0; - } - - /* check that the sum of all slices percentages (including removed/added - * slices) matches [1,100] */ - pct = 0; - for (i = 0; i < n_ex; i++) { - pct += existing[i]->percentage; - } - pct_orig = pct; - for (i = 0; i < n_up; i++) { - /* if there is an existing slice, subtract its percentage and add the - * update's percentage */ - if (s[i]) - pct -= s[i]->percentage; - pct += update[i]->percentage; - } - if (pct < 1 || pct > 100) { - LOG_E(FLEXRAN_AGENT, "[%d] invalid total RB share (%d%% -> %d%%)\n", - mod_id, pct_orig, pct); - return 0; - } - - /* check that there is no overlap in slices resulting as the combination of - * first_rb and percentage */ - struct sregion_s sregion[n]; - const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */ - int k = n_ex; - for (i = 0; i < n_ex; i++) { - sregion[i].start = existing[i]->first_rb; - sregion[i].length = existing[i]->percentage * N_RB / 100; - } - for (i = 0; i < n_up; i++) { - ptrdiff_t d = s[i] ? offs[i] : k++; - AssertFatal(d >= 0 && d < k, "illegal pointer offset (%ld, k=%d)\n", d, k); - sregion[d].start = update[i]->first_rb; - sregion[d].length = update[i]->percentage * N_RB / 100; - } - AssertFatal(k == n, "illegal number of slices while calculating overlap\n"); - if (!check_ul_slice_overlap(mod_id, sregion, k)) { - LOG_E(FLEXRAN_AGENT, "[%d] UL slices are overlapping\n", mod_id); - return 0; - } - - return 1; -} - -int flexran_dl_slice_verify_pct(int pct) -{ - return pct >= 0 && pct <= 100; -} - -int flexran_dl_slice_verify_priority(int prio) -{ - return prio >= 0; -} - -int flexran_dl_slice_verify_position(int pos_low, int pos_high) -{ - return pos_low < pos_high && pos_low >= 0 && pos_high <= N_RBG_MAX; -} - -int flexran_dl_slice_verify_maxmcs(int maxmcs) -{ - return maxmcs >= 0 && maxmcs <= 28; -} - -int flexran_ul_slice_verify_pct(int pct) -{ - return pct >= 0 && pct <= 100; -} - -int flexran_ul_slice_verify_priority(int prio) -{ - return prio >= 0; -} - -int flexran_ul_slice_verify_first_rb(int first_rb) -{ - return first_rb >= 0 && first_rb < 100; -} - -int flexran_ul_slice_verify_maxmcs(int maxmcs) -{ - return maxmcs >= 0 && maxmcs <= 20; -} - -int sregion_compare(const void *_a, const void *_b) -{ - const struct sregion_s *a = (const struct sregion_s *)_a; - const struct sregion_s *b = (const struct sregion_s *)_b; - const int res = a->start - b->start; - if (res < 0) return -1; - else if (res == 0) return 0; - else return 1; -} - -int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n) -{ - int i; - int overlap, op, u; - const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */ - qsort(sr, n, sizeof(sr[0]), sregion_compare); - for (i = 0; i < n; i++) { - u = i == n-1 ? N_RB : sr[i+1].start; - AssertFatal(sr[i].start <= u, "unsorted slice list\n"); - overlap = sr[i].start + sr[i].length - u; - if (overlap <= 0) continue; - op = overlap * 100 / sr[i].length; - LOG_W(FLEXRAN_AGENT, "[%d] slice overlap of %d%% detected\n", mod_id, op); - if (op >= 10) /* more than 10% overlap -> refuse */ - return 0; - } - return 1; -} diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h index a8f4030d36..c9e66b6f88 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h @@ -29,9 +29,3 @@ #include "flexran_agent_common_internal.h" #include "flexran_agent_mac_internal.h" -int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls); -int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing, - int n_ex, Protocol__FlexDlSlice **update, int n_up); -int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls); -int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing, - int n_ex, Protocol__FlexUlSlice **update, int n_up); diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c index 04a47406e1..c2d7cb9e55 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c @@ -125,6 +125,63 @@ void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply) { } } +void flexran_agent_handle_mme_update(mid_t mod_id, + size_t n_mme, + Protocol__FlexS1apMme **mme) { + if (n_mme == 0 || n_mme > 1) { + LOG_E(FLEXRAN_AGENT, "cannot handle %lu MMEs yet\n", n_mme); + return; + } + + if (!mme[0]->s1_ip) { + LOG_E(FLEXRAN_AGENT, "no S1 IP present, cannot handle request\n"); + return; + } + + if (mme[0]->has_state + && mme[0]->state == PROTOCOL__FLEX_MME_STATE__FLMMES_DISCONNECTED) { + int rc = flexran_remove_s1ap_mme(mod_id, 1, &mme[0]->s1_ip); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "remove MME at IP %s\n", mme[0]->s1_ip); + else + LOG_W(FLEXRAN_AGENT, + "could not remove MME: flexran_remove_s1ap_mme() returned %d\n", + rc); + } else { + int rc = flexran_add_s1ap_mme(mod_id, 1, &mme[0]->s1_ip); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "add MME at IP %s\n", mme[0]->s1_ip); + else + LOG_W(FLEXRAN_AGENT, + "could not add MME: flexran_add_s1ap_mme() returned %d\n", + rc); + } +} + +void flexran_agent_handle_plmn_update(mid_t mod_id, + int CC_id, + size_t n_plmn, + Protocol__FlexPlmn **plmn_id) { + if (n_plmn < 1 || n_plmn > 6) { + LOG_E(FLEXRAN_AGENT, "cannot handle %lu PLMNs\n", n_plmn); + return; + } + + /* We assume the controller has checked all the parameters within each + * plmn_id */ + int rc = flexran_set_new_plmn_id(mod_id, CC_id, n_plmn, plmn_id); + if (rc == 0) { + LOG_I(FLEXRAN_AGENT, "set %lu new PLMNs:\n", n_plmn); + for (int i = 0; i < (int)n_plmn; ++i) + LOG_I(FLEXRAN_AGENT, " MCC %d MNC %d MNC length %d\n", + plmn_id[i]->mcc, plmn_id[i]->mnc, plmn_id[0]->mnc_length); + } else { + LOG_W(FLEXRAN_AGENT, + "could not set new PLMN configuration: flexran_set_new_plmn_id() returned %d\n", + rc); + } +} + int flexran_agent_register_s1ap_xface(mid_t mod_id) { if (agent_s1ap_xface[mod_id]) { LOG_E(FLEXRAN_AGENT, "S1AP agent CM for eNB %d is already registered\n", mod_id); diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h index 1cca6ac9c1..006eaa1d3c 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h @@ -60,6 +60,17 @@ int flexran_agent_s1ap_stats_reply(mid_t mod_id, /* Free allocated S1AP stats message */ void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply); +/* Add or remove MME updates */ +void flexran_agent_handle_mme_update(mid_t mod_id, + size_t n_mme, + Protocol__FlexS1apMme **mme); + +/* Set a new PLMN configuration */ +void flexran_agent_handle_plmn_update(mid_t mod_id, + int CC_id, + size_t n_plmn, + Protocol__FlexPlmn **plmn_id); + /* Register technology specific interface callbacks */ int flexran_agent_register_s1ap_xface(mid_t mod_id); diff --git a/openair2/ENB_APP/MACRLC_paramdef.h b/openair2/ENB_APP/MACRLC_paramdef.h index 55ce9d5059..fcee6142f0 100644 --- a/openair2/ENB_APP/MACRLC_paramdef.h +++ b/openair2/ENB_APP/MACRLC_paramdef.h @@ -58,6 +58,7 @@ #define CONFIG_STRING_MACRLC_SCHED_MODE "scheduler_mode" #define CONFIG_MACRLC_PUSCH10xSNR "puSch10xSnr" #define CONFIG_MACRLC_PUCCH10xSNR "puCch10xSnr" +#define CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO "default_sched_dl_algo" /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* MacRLC configuration parameters */ @@ -84,6 +85,7 @@ {CONFIG_STRING_MACRLC_SCHED_MODE, NULL, 0, strptr:NULL, defstrval:"default", TYPE_STRING, 0}, \ {CONFIG_MACRLC_PUSCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ {CONFIG_MACRLC_PUCCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO, NULL, 0, strptr:NULL, defstrval:"round_robin_dl", TYPE_STRING, 0}, \ } #define MACRLC_CC_IDX 0 #define MACRLC_TRANSPORT_N_PREFERENCE_IDX 1 @@ -105,6 +107,7 @@ #define MACRLC_SCHED_MODE_IDX 17 #define MACRLC_PUSCH10xSNR_IDX 18 #define MACRLC_PUCCH10xSNR_IDX 19 +#define MACRLC_DEFAULT_SCHED_DL_ALGO_IDX 20 /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/ENB_APP/MESSAGES/V2/config_common.proto b/openair2/ENB_APP/MESSAGES/V2/config_common.proto index 733d883c92..2f2267b628 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_common.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_common.proto @@ -61,82 +61,30 @@ enum flex_qam { // // Slice config related structures and enums // -enum flex_dl_sorting { - - CR_ROUND = 0; // Highest HARQ first - CR_SRB12 = 1; // Highest SRB1+2 first - CR_HOL = 2; // Highest HOL first - CR_LC = 3; // Greatest RLC buffer first - CR_CQI = 4; // Highest CQI first - CR_LCP = 5; // Highest LC priority first +enum flex_slice_algorithm { + None = 0; + Static = 1; + NVS = 2; } -enum flex_ul_sorting { - CRU_ROUND = 0; // Highest HARQ first - CRU_BUF = 1; // Highest BSR first - CRU_BTS = 2; // More bytes to schedule first - CRU_MCS = 3; // Highest MCS first - CRU_LCP = 4; // Highest LC priority first - CRU_HOL = 5; // Highest HOL first +message flex_slice_static { + optional uint32 posLow = 1; + optional uint32 posHigh = 2; } -enum flex_dl_accounting_policy { - POL_FAIR = 0; - POL_GREEDY = 1; - POL_NUM = 2; +message flex_slice { + optional uint32 id = 1; + optional string label = 2; + optional string scheduler = 3; + oneof params { + flex_slice_static static = 10; + } } -enum flex_ul_accounting_policy { - POLU_FAIR = 0; - POLU_GREEDY = 1; - POLU_NUM = 2; -} - -enum flex_slice_label { - xMBB = 0; - URLLC = 1; - mMTC = 2; - xMTC = 3; - Other = 4; -} - -message flex_dl_slice { - optional uint32 id = 1; - optional flex_slice_label label = 2; - // should be between 0 and 100 - optional uint32 percentage = 3; - // whether this slice should be exempted form interslice sharing - optional bool isolation = 4; - // increasing value means increasing prio - optional uint32 priority = 5; - // min and max RB to use (in frequency) in the range [0, N_RBG_MAX] - optional uint32 position_low = 6; - optional uint32 position_high = 7; - // maximum MCS to be allowed in this slice - optional uint32 maxmcs = 8; - repeated flex_dl_sorting sorting = 9; - optional flex_dl_accounting_policy accounting = 10; - optional string scheduler_name = 11; -} - -message flex_ul_slice { - optional uint32 id = 1; - optional flex_slice_label label = 2; - // should be between 0 and 100 - optional uint32 percentage = 3; - // whether this slice should be exempted form interslice sharing - optional bool isolation = 4; - // increasing value means increasing prio - optional uint32 priority = 5; - // RB start to use (in frequency) in the range [0, N_RB_MAX] - optional uint32 first_rb = 6; - // TODO RB number - //optional uint32 length_rb = 7; - // maximum MCS to be allowed in this slice - optional uint32 maxmcs = 8; - repeated flex_ul_sorting sorting = 9; - optional flex_ul_accounting_policy accounting = 10; - optional string scheduler_name = 11; +message flex_slice_dl_ul_config { + optional flex_slice_algorithm algorithm = 1; + repeated flex_slice slices = 2; + optional string scheduler = 3; // if no slicing } // diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto index 324153613d..1a69deec71 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto @@ -49,14 +49,8 @@ message flex_cell_config { } message flex_slice_config { - // whether remaining RBs after first intra-slice allocation will - // be allocated to UEs of the same slice - optional bool intraslice_share_active = 3; - // whether remaining RBs after slice allocation will be allocated - // to UEs of another slice. Isolated slices will be ignored. - optional bool interslice_share_active = 4; - repeated flex_dl_slice dl = 1; - repeated flex_ul_slice ul = 2; + optional flex_slice_dl_ul_config dl = 6; + optional flex_slice_dl_ul_config ul = 7; } message flex_ue_config { diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 0e1c7e64bc..7c91e57813 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -273,7 +273,6 @@ void *eNB_app_task(void *args_p) { if (EPC_MODE_ENABLED) { LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), S1AP_REGISTER_ENB_CNF(msg_p).nb_mme); - DevAssert(register_enb_pending > 0); register_enb_pending--; /* Check if at least eNB is registered with one MME */ diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 2200c8f013..1d189832b4 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -29,6 +29,7 @@ #include #include +#include #include "common/utils/LOG/log.h" #include "assertions.h" @@ -260,6 +261,16 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) { global_scheduler_mode=SCHED_MODE_DEFAULT; printf("sched mode = default %d [%s]\n",global_scheduler_mode,*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr)); } + + char *s = *MacRLC_ParamList.paramarray[j][MACRLC_DEFAULT_SCHED_DL_ALGO_IDX].strptr; + void *d = dlsym(NULL, s); + AssertFatal(d, "%s(): no default scheduler DL algo '%s' found\n", __func__, s); + // release default, add new + pp_impl_param_t *dl_pp = &RC.mac[j]->pre_processor_dl; + dl_pp->dl_algo.unset(&dl_pp->dl_algo.data); + dl_pp->dl_algo = *(default_sched_dl_algo_t *) d; + dl_pp->dl_algo.data = dl_pp->dl_algo.setup(); + LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", dl_pp->dl_algo.name); }// j=0..num_inst } /*else {// MacRLC_ParamList.numelt > 0 // ignore it diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index dc320ef974..7569ca1ac1 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -306,6 +306,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { if (reply->cell_config[i]->mbsfn_subframe_config_sfalloc) free(reply->cell_config[i]->mbsfn_subframe_config_sfalloc); + /* si_config is shared between MAC and RRC, free here */ if (reply->cell_config[i]->si_config) { for(int j = 0; j < reply->cell_config[i]->si_config->n_si_message; j++) { free(reply->cell_config[i]->si_config->si_message[j]); @@ -316,26 +317,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { } if (reply->cell_config[i]->slice_config) { - for (int j = 0; j < reply->cell_config[i]->slice_config->n_dl; ++j) { - if (reply->cell_config[i]->slice_config->dl[j]->n_sorting > 0) - free(reply->cell_config[i]->slice_config->dl[j]->sorting); - - free(reply->cell_config[i]->slice_config->dl[j]->scheduler_name); - free(reply->cell_config[i]->slice_config->dl[j]); - } - - free(reply->cell_config[i]->slice_config->dl); - - for (int j = 0; j < reply->cell_config[i]->slice_config->n_ul; ++j) { - if (reply->cell_config[i]->slice_config->ul[j]->n_sorting > 0) - free(reply->cell_config[i]->slice_config->ul[j]->sorting); - - free(reply->cell_config[i]->slice_config->ul[j]->scheduler_name); - free(reply->cell_config[i]->slice_config->ul[j]); - } - - free(reply->cell_config[i]->slice_config->ul); - free(reply->cell_config[i]->slice_config); + flexran_agent_destroy_mac_slice_config(reply->cell_config[i]); } free(reply->cell_config[i]); @@ -893,31 +875,40 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexEnbConfigReply *enb_config = input->enb_config_reply_msg; - if (enb_config->n_cell_config == 0) { - LOG_W(FLEXRAN_AGENT, - "received enb_config_reply message does not contain a cell_config\n"); - *msg = NULL; - return 0; - } - if (enb_config->n_cell_config > 1) LOG_W(FLEXRAN_AGENT, "ignoring slice configs for other cell except cell 0\n"); - if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { - prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config); - } else if (enb_config->cell_config[0]->has_eutra_band - && enb_config->cell_config[0]->has_dl_freq - && enb_config->cell_config[0]->has_ul_freq - && enb_config->cell_config[0]->has_dl_bandwidth) { - initiate_soft_restart(mod_id, enb_config->cell_config[0]); - } else if (flexran_agent_get_rrc_xface(mod_id) - && enb_config->cell_config[0]->has_x2_ho_net_control) { - LOG_I(FLEXRAN_AGENT, - "setting X2 HO NetControl to %d\n", - enb_config->cell_config[0]->x2_ho_net_control); - const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control); - if (rc < 0) - LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); + if (enb_config->n_cell_config > 0) { + if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { + prepare_update_slice_config(mod_id, &enb_config->cell_config[0]->slice_config); + } + if (enb_config->cell_config[0]->has_eutra_band + && enb_config->cell_config[0]->has_dl_freq + && enb_config->cell_config[0]->has_ul_freq + && enb_config->cell_config[0]->has_dl_bandwidth) { + initiate_soft_restart(mod_id, enb_config->cell_config[0]); + } + if (flexran_agent_get_rrc_xface(mod_id) + && enb_config->cell_config[0]->has_x2_ho_net_control) { + LOG_I(FLEXRAN_AGENT, + "setting X2 HO NetControl to %d\n", + enb_config->cell_config[0]->x2_ho_net_control); + const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control); + if (rc < 0) + LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); + } + if (flexran_agent_get_rrc_xface(mod_id) && enb_config->cell_config[0]->n_plmn_id > 0) { + flexran_agent_handle_plmn_update(mod_id, + 0, + enb_config->cell_config[0]->n_plmn_id, + enb_config->cell_config[0]->plmn_id); + } + } + + if (flexran_agent_get_s1ap_xface(mod_id) && enb_config->s1ap) { + flexran_agent_handle_mme_update(mod_id, + enb_config->s1ap->n_mme, + enb_config->s1ap->mme); } *msg = NULL; @@ -930,7 +921,11 @@ int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void *params, Proto Protocol__FlexUeConfigReply *ue_config_reply = input->ue_config_reply_msg; for (i = 0; flexran_agent_get_mac_xface(mod_id) && i < ue_config_reply->n_ue_config; i++) - prepare_ue_slice_assoc_update(mod_id, ue_config_reply->ue_config[i]); + prepare_ue_slice_assoc_update(mod_id, &ue_config_reply->ue_config[i]); + /* prepare_ue_slice_assoc_update takes ownership of the individual + * FlexUeConfig messages. Therefore, mark zero messages to not accidentally + * free them twice */ + ue_config_reply->n_ue_config = 0; *msg = NULL; return 0; diff --git a/openair2/ENB_APP/flexran_agent_extern.h b/openair2/ENB_APP/flexran_agent_extern.h index 5f17cf4841..2a5930e1a8 100644 --- a/openair2/ENB_APP/flexran_agent_extern.h +++ b/openair2/ENB_APP/flexran_agent_extern.h @@ -44,8 +44,6 @@ AGENT_PHY_xface *flexran_agent_get_phy_xface(mid_t mod_id); extern AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB]; #define flexran_agent_get_mac_xface(mod_id) (agent_mac_xface[mod_id]) -/* Control module interface for the communication of the RRC Control Module with the agent */ - /* Control module interface for the communication of the RRC Control Module with the agent */ // AGENT_RRC_xface *flexran_agent_get_rrc_xface(mid_t mod_id); extern AGENT_RRC_xface *agent_rrc_xface[NUM_MAX_ENB]; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 32cb8c74e1..79c992a4d7 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -30,6 +30,7 @@ #include "flexran_agent_ran_api.h" #include "s1ap_eNB_ue_context.h" #include "s1ap_eNB_management_procedures.h" +#include "openair2/LAYER2/MAC/slicing/slicing.h" static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) { return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id]; @@ -3013,471 +3014,293 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti) } /**************************** SLICING ****************************/ -int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { - if (!mac_is_present(mod_id)) return -1; +Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id) { + if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None; - 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; - - return 0; + switch (RC.mac[mod_id]->pre_processor_dl.algorithm) { + case STATIC_SLICING: + return PROTOCOL__FLEX_SLICE_ALGORITHM__Static; + default: + return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + } } -void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { +int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return 0; + eNB_MAC_INST *mac = RC.mac[mod_id]; + const int cc_id = 0; + + pp_impl_param_t dl = mac->pre_processor_dl; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + mac->pre_processor_dl = static_dl_init(mod_id, cc_id); + break; + default: + mac->pre_processor_dl.algorithm = 0; + mac->pre_processor_dl.dl = dlsch_scheduler_pre_processor; + mac->pre_processor_dl.dl_algo.data = mac->pre_processor_dl.dl_algo.setup(); + mac->pre_processor_dl.slices = NULL; + break; + } + if (dl.slices) + dl.destroy(&dl.slices); + if (dl.dl_algo.data) + dl.dl_algo.unset(&dl.dl_algo.data); + return 1; +} + +Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id) { + if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + + switch (RC.mac[mod_id]->pre_processor_ul.algorithm) { + case STATIC_SLICING: + return PROTOCOL__FLEX_SLICE_ALGORITHM__Static; + default: + return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + } +} + +int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return 0; + eNB_MAC_INST *mac = RC.mac[mod_id]; + const int cc_id = 0; + + pp_impl_param_t ul = mac->pre_processor_ul; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + mac->pre_processor_ul = static_ul_init(mod_id, cc_id); + break; + default: + mac->pre_processor_ul.algorithm = 0; + mac->pre_processor_ul.ul = ulsch_scheduler_pre_processor; + mac->pre_processor_ul.ul_algo.data = mac->pre_processor_ul.ul_algo.setup(); + mac->pre_processor_ul.slices = NULL; + break; + } + if (ul.slices) + ul.destroy(&ul.slices); + if (ul.ul_algo.data) + ul.ul_algo.unset(&ul.ul_algo.data); + return 1; +} + +int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { + if (!mac_is_present(mod_id)) return -1; + slice_info_t *slices = RC.mac[mod_id]->pre_processor_dl.slices; + if (!slices) return -1; + const int idx = slices->UE_assoc_slice[ue_id]; + return slices->s[idx]->id; +} + +void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return; - - if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return; - - if (!flexran_dl_slice_exists(mod_id, slice_idx)) return; - - //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id] = slice_idx; + int idx = flexran_find_dl_slice(mod_id, slice_id); + if (idx < 0) return; + pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; + dl->move_UE(dl->slices, ue_id, 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 = 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; - - return 0; + slice_info_t *slices = RC.mac[mod_id]->pre_processor_ul.slices; + if (!slices) return -1; + const int idx = slices->UE_assoc_slice[ue_id]; + return slices->s[idx]->id; } -void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { +void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return; - - if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return; - - if (!flexran_ul_slice_exists(mod_id, slice_idx)) return; - - //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx; + int idx = flexran_find_ul_slice(mod_id, slice_id); + if (idx < 0) return; + pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; + ul->move_UE(ul->slices, ue_id, idx); } -int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl; +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return 0; + void *params = NULL; + switch (s->params_case) { + case PROTOCOL__FLEX_SLICE__PARAMS_STATIC: + params = malloc(sizeof(static_slice_param_t)); + if (!params) return 0; + ((static_slice_param_t *)params)->posLow = s->static_->poslow; + ((static_slice_param_t *)params)->posHigh = s->static_->poshigh; + break; + default: + break; + } + pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; + char *l = s->label ? strdup(s->label) : NULL; + void *algo = &dl->dl_algo; // default scheduler + if (s->scheduler) { + algo = dlsym(NULL, s->scheduler); + if (!algo) { + free(params); + LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); + return -15; + } + } + return dl->addmod_slice(dl->slices, s->id, l, algo, params); } -int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return -1; - - int newidx = RC.mac[mod_id]->slice_info.n_dl; - - if (newidx >= MAX_NUM_SLICES) return -1; - - ++RC.mac[mod_id]->slice_info.n_dl; - flexran_set_dl_slice_id(mod_id, newidx, slice_id); - return newidx; +int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return 0; + const int idx = flexran_find_dl_slice(mod_id, s->id); + if (idx < 0) return 0; + pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; + return dl->remove_slice(dl->slices, idx); } int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - int n = sli->n_dl; - - for (int i = 0; i < n; i++) { - if (sli->dl[i].id == slice_id) return i; - } - + slice_info_t *si = RC.mac[mod_id]->pre_processor_dl.slices; + for (int i = 0; i < si->num; ++i) + if (si->s[i]->id == slice_id) + return i; return -1; } -int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - - if (sli->n_dl <= 1) return -1; - - if (sli->dl[slice_idx].sched_name) free(sli->dl[slice_idx].sched_name); - - --sli->n_dl; - - /* move last element to the position of the removed one */ - if (slice_idx != sli->n_dl) - memcpy(&sli->dl[slice_idx], &sli->dl[sli->n_dl], sizeof(sli->dl[sli->n_dl])); - - 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_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; - //} - - return 1; +void flexran_get_dl_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return; + slice_t *s_ = RC.mac[mod_id]->pre_processor_dl.slices->s[slice_idx]; + slice->has_id = 1; + slice->id = s_->id; + slice->label = s_->label; + slice->scheduler = s_->dl_algo.name; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic)); + if (!slice->static_) return; + protocol__flex_slice_static__init(slice->static_); + slice->static_->has_poslow = 1; + slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow; + slice->static_->has_poshigh = 1; + slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC; + break; + default: + break; + } } int flexran_get_num_dl_slices(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.n_dl; -} - -int flexran_get_intraslice_sharing_active(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.intraslice_share_active; -} -void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.intraslice_share_active = intraslice_active; -} - -int flexran_get_interslice_sharing_active(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.interslice_share_active; -} -void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.interslice_share_active = interslice_active; -} - -slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].id; -} -void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].id = slice_id; -} - -int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].pct * 100.0f; -} -void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pct = percentage / 100.0f; -} - -int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].isol; -} -void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].isol = is_isolated; -} - -int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].prio; -} -void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].prio = priority; -} - -int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low; -} -void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low = poslow; -} - -int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high; -} -void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high = poshigh; -} - -int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs; -} -void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs = maxmcs; -} - -int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list) { - if (!mac_is_present(mod_id)) return -1; - - if (!(*sorting_list)) { - *sorting_list = calloc(CR_NUM, sizeof(Protocol__FlexDlSorting)); - - if (!(*sorting_list)) return -1; - } - - uint32_t policy = RC.mac[mod_id]->slice_info.dl[slice_idx].sorting; - - for (int i = 0; i < CR_NUM; i++) { - switch (policy >> 4 * (CR_NUM - 1 - i) & 0xF) { - case CR_ROUND: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND; - break; - - case CR_SRB12: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_SRB12; - break; - - case CR_HOL: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_HOL; - break; - - case CR_LC: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LC; - break; - - case CR_CQI: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_CQI; - break; - - case CR_LCP: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LCP; - break; - - default: - /* this should not happen, but a "default" */ - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND; - break; - } - } - - return CR_NUM; -} -void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n) { - if (!mac_is_present(mod_id)) return; - - uint32_t policy = 0; - - for (int i = 0; i < n && i < CR_NUM; i++) { - switch (sorting_list[i]) { - case PROTOCOL__FLEX_DL_SORTING__CR_ROUND: - policy = policy << 4 | CR_ROUND; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_SRB12: - policy = policy << 4 | CR_SRB12; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_HOL: - policy = policy << 4 | CR_HOL; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_LC: - policy = policy << 4 | CR_LC; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_CQI: - policy = policy << 4 | CR_CQI; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_LCP: - policy = policy << 4 | CR_LCP; - break; - - default: /* suppresses warnings */ - policy = policy << 4 | CR_ROUND; - break; - } - } - - /* fill up with 0 == CR_ROUND */ - if (CR_NUM > n) policy = policy << 4 * (CR_NUM - n); - - RC.mac[mod_id]->slice_info.dl[slice_idx].sorting = policy; -} - -Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - - switch (RC.mac[mod_id]->slice_info.dl[slice_idx].accounting) { - case POL_FAIR: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - - case POL_GREEDY: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY; - - default: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - } -} -void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting) { - if (!mac_is_present(mod_id)) return; - - switch (accounting) { - case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR: - RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR; - return; - - case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY: - RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_GREEDY; - return; - - default: - RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR; - return; - } -} - -char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return NULL; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name; -} -int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { if (!mac_is_present(mod_id)) return 0; - - if (RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name) - free(RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name); - - RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name = strdup(name); - RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb = dlsym(NULL, name); - return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb != NULL; + if (!RC.mac[mod_id]->pre_processor_dl.slices) return 0; + return RC.mac[mod_id]->pre_processor_dl.slices->num; } -int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) { +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { if (!mac_is_present(mod_id)) return -1; + void *params = NULL; + switch (s->params_case) { + case PROTOCOL__FLEX_SLICE__PARAMS_STATIC: + params = malloc(sizeof(static_slice_param_t)); + if (!params) return 0; + ((static_slice_param_t *)params)->posLow = s->static_->poslow; + ((static_slice_param_t *)params)->posHigh = s->static_->poshigh; + break; + default: + break; + } + pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; + char *l = s->label ? strdup(s->label) : NULL; + void *algo = &ul->ul_algo; // default scheduler + if (s->scheduler) { + algo = dlsym(NULL, s->scheduler); + if (!algo) { + free(params); + LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); + return -15; + } + } + return ul->addmod_slice(ul->slices, s->id, l, algo, params); +} - int newidx = RC.mac[mod_id]->slice_info.n_ul; - - if (newidx >= MAX_NUM_SLICES) return -1; - - ++RC.mac[mod_id]->slice_info.n_ul; - flexran_set_ul_slice_id(mod_id, newidx, slice_id); - return newidx; +int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return 0; + const int idx = flexran_find_ul_slice(mod_id, s->id); + if (idx < 0) return 0; + pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; + return ul->remove_slice(ul->slices, idx); } int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - int n = sli->n_ul; - - for (int i = 0; i < n; i++) { - if (sli->ul[i].id == slice_id) return i; - } - + slice_info_t *si = RC.mac[mod_id]->pre_processor_ul.slices; + for (int i = 0; i < si->num; ++i) + if (si->s[i]->id == slice_id) + return i; return -1; } -int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; +void flexran_get_ul_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return; + slice_t *s_ = RC.mac[mod_id]->pre_processor_ul.slices->s[slice_idx]; + slice->has_id = 1; + slice->id = s_->id; + slice->label = s_->label; + slice->scheduler = s_->ul_algo.name; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic)); + if (!slice->static_) return; + protocol__flex_slice_static__init(slice->static_); + slice->static_->has_poslow = 1; + slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow; + slice->static_->has_poshigh = 1; + slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC; + break; + default: + break; + } - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - - if (sli->n_ul <= 1) return -1; - - if (sli->ul[slice_idx].sched_name) free(sli->ul[slice_idx].sched_name); - - --sli->n_ul; - - /* move last element to the position of the removed one */ - if (slice_idx != sli->n_ul) - memcpy(&sli->ul[slice_idx], &sli->ul[sli->n_ul], sizeof(sli->ul[sli->n_ul])); - - 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_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; - //} - - return sli->n_ul; } int flexran_get_num_ul_slices(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.n_ul; -} - -int flexran_ul_slice_exists(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul; -} - -slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].id; -} -void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].id = slice_id; -} - -int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].pct * 100.0f; -} -void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].pct = percentage / 100.0f; -} - -int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb; -} - -void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb = first_rb; -} - -int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs; -} -void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { - if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs = maxmcs; -} - -char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return NULL; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name; -} -int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { if (!mac_is_present(mod_id)) return 0; + if (!RC.mac[mod_id]->pre_processor_ul.slices) return 0; + return RC.mac[mod_id]->pre_processor_ul.slices->num; +} - if (RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name) - free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name); +char *flexran_get_dl_scheduler_name(mid_t mod_id) { + if (!mac_is_present(mod_id)) return NULL; + return RC.mac[mod_id]->pre_processor_dl.dl_algo.name; +} - RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name = strdup(name); - RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb = dlsym(NULL, name); - return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL; +int flexran_set_dl_scheduler(mid_t mod_id, char *sched) { + if (!mac_is_present(mod_id)) return -1; + void *d = dlsym(NULL, sched); + if (!d) return -2; + pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl; + dl_pp->dl_algo.unset(&dl_pp->dl_algo.data); + dl_pp->dl_algo = *(default_sched_dl_algo_t *) d; + dl_pp->dl_algo.data = dl_pp->dl_algo.setup(); + return 0; +} + +char *flexran_get_ul_scheduler_name(mid_t mod_id) { + if (!mac_is_present(mod_id)) return NULL; + return RC.mac[mod_id]->pre_processor_ul.ul_algo.name; +} + +int flexran_set_ul_scheduler(mid_t mod_id, char *sched) { + if (!mac_is_present(mod_id)) return -1; + void *d = dlsym(NULL, sched); + if (!d) return -2; + pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul; + ul_pp->ul_algo.unset(&ul_pp->ul_algo.data); + ul_pp->ul_algo = *(default_sched_ul_algo_t *) d; + ul_pp->ul_algo.data = ul_pp->ul_algo.setup(); + return 0; } /************************** S1AP **************************/ @@ -3634,6 +3457,168 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM return 0; } +int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { + s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); + if (!s1ap) return -1; + if (!rrc_is_present(mod_id)) return -2; + + /* Reconstruct S1AP_REGISTER_ENB_REQ */ + MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, S1AP_REGISTER_ENB_REQ); + RCconfig_S1(m, mod_id); + + const int CC_id = 0; + eNB_RRC_INST *rrc = RC.rrc[CC_id]; + RrcConfigurationReq *conf = &rrc->configuration; + S1AP_REGISTER_ENB_REQ(m).num_plmn = conf->num_plmn; + for (int i = 0; i < conf->num_plmn; ++i) { + S1AP_REGISTER_ENB_REQ(m).mcc[i] = conf->mcc[i]; + S1AP_REGISTER_ENB_REQ(m).mnc[i] = conf->mnc[i]; + S1AP_REGISTER_ENB_REQ(m).mnc_digit_length[i] = conf->mnc_digit_length[i]; + } + + /* reconstruct MME list, it might have been updated since initial + * configuration */ + S1AP_REGISTER_ENB_REQ(m).nb_mme = 0; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) { + const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme; + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = mme->mme_s1_ip.ipv4; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme->mme_s1_ip.ipv4_address); + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = mme->mme_s1_ip.ipv6; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6_address, mme->mme_s1_ip.ipv6_address); + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = mme->broadcast_plmn_num; + for (int i = 0; i < mme->broadcast_plmn_num; ++i) + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = mme->broadcast_plmn_index[i]; + S1AP_REGISTER_ENB_REQ(m).nb_mme += 1; + } + + if (S1AP_REGISTER_ENB_REQ(m).nb_mme + n_mme > S1AP_MAX_NB_MME_IP_ADDRESS) + return -1; + + for (int i = 0; i < n_mme; ++i) { + const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]); + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1; + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0; + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn; + for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i) + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i; + S1AP_REGISTER_ENB_REQ(m).nb_mme += 1; + } + + itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m); + + return 0; +} + +int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { + s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); + if (!s1ap) return -1; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) { + if (mme->mme_s1_ip.ipv4 + && strncmp(mme->mme_s1_ip.ipv4_address, mme_ipv4[0], 16) == 0) + break; + } + if (!mme) + return -2; + + MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SCTP_CLOSE_ASSOCIATION); + SCTP_CLOSE_ASSOCIATION(m).assoc_id = mme->assoc_id; + itti_send_msg_to_task (TASK_SCTP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m); + + switch (mme->state) { + case S1AP_ENB_STATE_WAITING: + s1ap->s1ap_mme_nb -= 1; + if (s1ap->s1ap_mme_pending_nb > 0) + s1ap->s1ap_mme_pending_nb -= 1; + break; + case S1AP_ENB_STATE_CONNECTED: + case S1AP_ENB_OVERLOAD: /* I am not sure the decrements are right here */ + s1ap->s1ap_mme_nb -= 1; + s1ap->s1ap_mme_associated_nb -= 1; + break; + case S1AP_ENB_STATE_DISCONNECTED: + default: + break; + } + RB_REMOVE(s1ap_mme_map, &s1ap->s1ap_mme_head, mme); + + return 0; +} + +int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id) { + if (!rrc_is_present(mod_id)) + return -1; + s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); + if (!s1ap) + return -2; + + eNB_RRC_INST *rrc = RC.rrc[CC_id]; + RrcConfigurationReq *conf = &rrc->configuration; + + uint8_t num_plmn_old = conf->num_plmn; + uint16_t mcc[PLMN_LIST_MAX_SIZE]; + uint16_t mnc[PLMN_LIST_MAX_SIZE]; + uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE]; + for (int i = 0; i < num_plmn_old; ++i) { + mcc[i] = conf->mcc[i]; + mnc[i] = conf->mnc[i]; + mnc_digit_length[i] = conf->mnc_digit_length[i]; + } + + conf->num_plmn = (uint8_t) n_plmn; + for (int i = 0; i < conf->num_plmn; ++i) { + conf->mcc[i] = plmn_id[i]->mcc; + conf->mnc[i] = plmn_id[i]->mnc; + conf->mnc_digit_length[i] = plmn_id[i]->mnc_length; + } + + rrc_eNB_carrier_data_t *carrier = &rrc->carrier[CC_id]; + extern uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier, + int Mod_id, + int CC_id, + BOOLEAN_t brOption, + RrcConfigurationReq *configuration); + carrier->sizeof_SIB1 = do_SIB1(carrier, mod_id, CC_id, FALSE, conf); + if (carrier->sizeof_SIB1 < 0) + return -1337; /* SIB1 encoding failed, hell will probably break loose */ + + s1ap->num_plmn = (uint8_t) n_plmn; + for (int i = 0; i < conf->num_plmn; ++i) { + s1ap->mcc[i] = plmn_id[i]->mcc; + s1ap->mnc[i] = plmn_id[i]->mnc; + s1ap->mnc_digit_length[i] = plmn_id[i]->mnc_length; + } + + int bpn_failed = 0; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) { + for (int i = 0; i < mme->broadcast_plmn_num; ++i) { + /* search the new index and update. If we don't find, we count this using + * bpn_failed to now how many broadcast_plmns could not be updated */ + int idx = mme->broadcast_plmn_index[i]; + int omcc = mcc[idx]; + int omnc = mnc[idx]; + int omncl = mnc_digit_length[idx]; + int j = 0; + for (j = 0; j < s1ap->num_plmn; ++j) { + if (s1ap->mcc[j] == omcc + && s1ap->mnc[j] == omnc + && s1ap->mnc_digit_length[j] == omncl) { + mme->broadcast_plmn_index[i] = j; + break; + } + } + if (j == s1ap->num_plmn) /* could not find the old PLMN in the new ones */ + bpn_failed++; + } + } + if (bpn_failed > 0) + return -10000 - bpn_failed; + return 0; +} + int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){ if (!rrc_is_present(mod_id)) return -1; s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); @@ -3644,7 +3629,7 @@ int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_con RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head){ if (ue->eNB_ue_s1ap_id == enb_ue_s1ap_id) break; } - if (ue == NULL) return -1; + if (!ue) return 0; // UE does not exist: it might be connected but CN did not answer if (ue->mme_ref->mme_s1_ip.ipv4) ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv4_address[0]; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index ce32883852..2d8a86f7d0 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -656,156 +656,66 @@ int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index); uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti); /************************** Slice configuration **************************/ +/* Get the currently active DL slicing algorithm */ +Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id); +/* Set the active DL slicing algorithm */ +int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo); + +/* Get the currently active UL slicing algorithm */ +Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id); +/* Set the active UL slicing algorithm */ +int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo); /* Get the DL slice ID for a UE */ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id); - -/* Set the DL slice index(!) for a UE */ -void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); +/* Set the DL slice for a UE */ +void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); /* Get the UL slice ID for a UE */ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id); +/* Set the UL slice for a UE */ +void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); -/* Set the UL slice index(!) for a UE */ -void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); - -/* Whether intraslice sharing is active, return boolean */ -int flexran_get_intraslice_sharing_active(mid_t mod_id); -/* Set whether intraslice sharing is active */ -void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active); - -/* Whether intraslice sharing is active, return boolean */ -int flexran_get_interslice_sharing_active(mid_t mod_id); -/* Set whether intraslice sharing is active */ -void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active); +/* Create slice in DL, returns the new slice index */ +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); +/* Remove slice in DL, returns new number of slices or -1 on error */ +int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); +/* Finds slice in DL with given slice_id and returns slice index */ +int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id); +/* Return the parameters of slice at index slice_idx */ +void flexran_get_dl_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo); /* Get the number of slices in DL */ int flexran_get_num_dl_slices(mid_t mod_id); -/* Query slice existence in DL. Return is boolean value */ -int flexran_dl_slice_exists(mid_t mod_id, int slice_idx); +/* Create slice in UL, returns the new slice index */ +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); +/* Remove slice in UL */ +int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); -/* Create slice in DL, returns the new slice index */ -int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id); /* Finds slice in DL with given slice_id and returns slice index */ -int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id); -/* Remove slice in DL, returns new number of slices or -1 on error */ -int flexran_remove_dl_slice(mid_t mod_id, int slice_idx); - -/* Get the ID of a slice in DL */ -slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx); -/* Set the ID of a slice in DL */ -void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id); - -/* Get the RB share a slice in DL, value 0-100 */ -int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx); -/* Set the RB share a slice in DL, value 0-100 */ -void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage); - -/* Whether a slice in DL is isolated */ -int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx); -/* Set whether a slice in DL is isolated */ -void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated); - -/* Get the priority of a slice in DL */ -int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx); -/* Get the priority of a slice in DL */ -void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority); - -/* Get the lower end of the frequency range for the slice positioning in DL */ -int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx); -/* Set the lower end of the frequency range for the slice positioning in DL */ -void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow); - -/* Get the higher end of the frequency range for the slice positioning in DL */ -int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx); -/* Set the higher end of the frequency range for the slice positioning in DL */ -void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh); - -/* Get the maximum MCS for slice in DL */ -int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx); -/* Set the maximum MCS for slice in DL */ -void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs); - -/* Get the sorting order of a slice in DL, return value is number of elements - * in sorting_list */ -int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list); -/* Set the sorting order of a slice in DL */ -void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n); - -/* Get the accounting policy for a slice in DL */ -Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx); -/* Set the accounting policy for a slice in DL */ -void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting); - -/* Get the scheduler name for a slice in DL */ -char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx); -/* Set the scheduler name for a slice in DL */ -int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name); - +int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id); +/* Return the parameters of slice at index slice_idx */ +void flexran_get_ul_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo); /* Get the number of slices in UL */ int flexran_get_num_ul_slices(mid_t mod_id); -/* Query slice existence in UL. Return is boolean value */ -int flexran_ul_slice_exists(mid_t mod_id, int slice_idx); +/* Get the name of/Set the DL scheduling algorithm. If slicing is active, this + * corresponds to the default algorithm for slices, otherwise the currently + * used one. */ +char *flexran_get_dl_scheduler_name(mid_t mod_id); +int flexran_set_dl_scheduler(mid_t mod_id, char *sched); -/* Create slice in UL, returns the new slice index */ -int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id); -/* Finds slice in UL with given slice_id and returns slice index */ -int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id); -/* Remove slice in UL */ -int flexran_remove_ul_slice(mid_t mod_id, int slice_idx); - -/* Get the ID of a slice in UL */ -slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx); -/* Set the ID of a slice in UL */ -void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id); - -/* Get the RB share a slice in UL, value 0-100 */ -int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx); -/* Set the RB share a slice in UL, value 0-100 */ -void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage); - -/* TODO Whether a slice in UL is isolated */ -/*int flexran_get_ul_slice_isolation(mid_t mod_id, int slice_idx);*/ -/* TODO Set whether a slice in UL is isolated */ -/*void flexran_set_ul_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated);*/ - -/* TODO Get the priority of a slice in UL */ -/*int flexran_get_ul_slice_priority(mid_t mod_id, int slice_idx);*/ -/* TODO Set the priority of a slice in UL */ -/*void flexran_set_ul_slice_priority(mid_t mod_id, int slice_idx, int priority);*/ - -/* Get the first RB for allocation in a slice in UL */ -int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx); -/* Set the first RB for allocation in a slice in UL */ -void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb); - -/* TODO Get the number of RB for the allocation in a slice in UL */ -/*int flexran_get_ul_slice_length_rb(mid_t mod_id, int slice_idx);*/ -/* TODO Set the of number of RB for the allocation in a slice in UL */ -/*void flexran_set_ul_slice_length_rb(mid_t mod_id, int slice_idx, int poshigh);*/ - -/* Get the maximum MCS for slice in UL */ -int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx); -/* Set the maximum MCS for slice in UL */ -void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs); - -/* TODO Get the sorting order of a slice in UL, return value is number of elements - * in sorting_list */ -/*int flexran_get_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting **sorting_list);*/ -/* TODO Set the sorting order of a slice in UL */ -/*void flexran_set_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting *sorting_list, int n);*/ - -/* TODO Get the accounting policy for a slice in UL */ -/*Protocol__UlAccountingPolicy flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx);*/ -/* TODO Set the accounting policy for a slice in UL */ -/*void flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__UlAccountingPolicy accountin);*/ - -/* Get the scheduler name for a slice in UL */ -char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx); -/* Set the scheduler name for a slice in UL */ -int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name); +/* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL + * case */ +char *flexran_get_ul_scheduler_name(mid_t mod_id); +int flexran_set_ul_scheduler(mid_t mod_id, char *sched); /************************** S1AP **************************/ /* Get the number of MMEs to be connected */ @@ -832,6 +742,15 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM /* Get the S1AP UE conf */ int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf); +/* Add MMEs and re-issue S1AP Registration Request */ +int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); + +/* Remove MMEs and and cut SCTP to MME */ +int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); + +/* Set a new PLMN configuration */ +int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id); + /********************* general information *****************/ /* get an ID for this BS (or part of a BS) */ uint64_t flexran_get_bs_id(mid_t mod_id); diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index c46005ee2d..d184c7e439 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -547,7 +547,7 @@ copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { ul_req_tmp->ul_config_request_body.number_of_pdus = 0; if (ul_req->ul_config_request_body.number_of_pdus>0) { - LOG_D(PHY, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus); + LOG_D(MAC, "%s() active NOW (frameP:%d subframeP:%d) pdus:%d\n", __FUNCTION__, frameP, subframeP, ul_req->ul_config_request_body.number_of_pdus); } memcpy((void *)ul_req->ul_config_request_body.ul_config_pdu_list, @@ -556,6 +556,11 @@ copy_ulreq(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { } } +extern int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +extern int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +extern void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); +extern void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); + void eNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frameP, @@ -843,6 +848,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, } /* Note: This should not be done in the MAC! */ + /* for (int ii=0; iiulsch[ii]; @@ -862,6 +868,17 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, clean_eNb_dlsch(dlsch); } } + */ + + int id; + + // clean ULSCH entries for rnti + id = find_ulsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST); + if (id>=0) clean_eNb_ulsch(RC.eNB[module_idP][CC_id]->ulsch[id]); + + // clean DLSCH entries for rnti + id = find_dlsch(rnti,RC.eNB[module_idP][CC_id],SEARCH_EXIST); + if (id>=0) clean_eNb_dlsch(RC.eNB[module_idP][CC_id]->dlsch[id][0]); for (int j = 0; j < 10; j++) { nfapi_ul_config_request_body_t *ul_req_tmp = NULL; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 7621994ab2..1f99f50ece 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -573,10 +573,7 @@ schedule_ue_spec(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN); start_meas(&eNB->schedule_dlsch_preprocessor); - dlsch_scheduler_pre_processor(module_idP, - CC_id, - frameP, - subframeP); + eNB->pre_processor_dl.dl(module_idP, CC_id, frameP, subframeP); stop_meas(&eNB->schedule_dlsch_preprocessor); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT); @@ -588,6 +585,7 @@ schedule_ue_spec(module_id_t module_idP, 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]; + eNB_UE_stats->TBS = 0; const rnti_t rnti = ue_template->rnti; // If TDD @@ -679,15 +677,15 @@ schedule_ue_spec(module_id_t module_idP, 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", + if (nb_rb > ue_sched_ctrl->pre_nb_available_rbs[CC_id]) + LOG_W(MAC, + "[eNB %d] %d.%d CC_id %d : should not schedule UE %d, its " + "retransmission takes more resources than we have\n", module_idP, frameP, + subframeP, CC_id, UE_id); - continue; - } /* CDRX */ ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer @@ -799,6 +797,7 @@ schedule_ue_spec(module_id_t module_idP, 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; + eNB_UE_stats->TBS = TBS; } else { // Now check RLC information to compute number of required RBs // get maximum TBS size for RLC request @@ -842,13 +841,18 @@ schedule_ue_spec(module_id_t module_idP, 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", + const uint32_t data = + min(ue_sched_ctrl->dl_lc_bytes[i], + TBS - ta_len - header_length_total - sdu_length_total - 3); + 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); + data); sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, rnti, @@ -857,7 +861,7 @@ schedule_ue_spec(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS - ta_len - header_length_total - sdu_length_total - 3, + data, (char *)&dlsch_buffer[sdu_length_total], 0, 0 diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 00fd40109d..f6220fa46d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -2240,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]={0}; + 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]; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 78d6f6a3d7..89c2ecc83d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2131,33 +2131,36 @@ dump_ue_list(UE_list_t *listP) { * 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 { - int i = listP->head; - while (listP->next[i] >= 0) - i = listP->next[i]; - listP->next[i] = UE_id; - listP->next[UE_id] = -1; - } + int *cur = &listP->head; + while (*cur >= 0) + cur = &listP->next[*cur]; + *cur = UE_id; } //------------------------------------------------------------------------------ /* - * Remove a UE from the UE_list listP, return the previous element + * Remove a UE from the UE_list listP */ 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; - } + int *cur = &listP->head; + while (*cur != -1 && *cur != UE_id) + cur = &listP->next[*cur]; + if (*cur == -1) + return 0; + int *next = &listP->next[*cur]; + *cur = listP->next[*cur]; + *next = -1; + return 1; +} - int previous = prev(listP, UE_id); - if (previous != -1) - listP->next[previous] = listP->next[UE_id]; - return previous; +//------------------------------------------------------------------------------ +/* + * Initialize the UE_list listP + */ +inline void init_ue_list(UE_list_t *listP) { + listP->head = -1; + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + listP->next[i] = -1; } //------------------------------------------------------------------------------ @@ -2196,6 +2199,12 @@ add_new_ue(module_id_t mod_idP, UE_info->active[UE_id] = TRUE; add_ue_list(&UE_info->list, UE_id); dump_ue_list(&UE_info->list); + pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl; + if (dl->slices) // inform slice implementation about new UE + dl->add_UE(dl->slices, UE_id); + pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul; + if (ul->slices) // inform slice implementation about new UE + ul->add_UE(ul->slices, UE_id); if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ? 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; @@ -2259,6 +2268,12 @@ rrc_mac_remove_ue(module_id_t mod_idP, UE_info->num_UEs--; remove_ue_list(&UE_info->list, UE_id); + pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl; + if (dl->slices) // inform slice implementation about new UE + dl->remove_UE(dl->slices, UE_id); + pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul; + if (ul->slices) // inform slice implementation about new UE + ul->remove_UE(ul->slices, UE_id); /* Clear all remaining pending transmissions */ memset(&UE_info->UE_template[pCC_id][UE_id], 0, sizeof(UE_TEMPLATE)); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 3062e5c964..2de45db856 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1301,11 +1301,11 @@ schedule_ulsch_rnti(module_id_t module_idP, /* * ULSCH preprocessor: set UE_template-> - * pre_allocated_nb_rb_ul[slice_idx] + * pre_allocated_nb_rb_ul * pre_assigned_mcs_ul * pre_allocated_rb_table_index_ul */ - ulsch_scheduler_pre_processor(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP); + mac->pre_processor_ul.ul(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP); 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) diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 329e262c82..faefc481f6 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -155,9 +155,6 @@ /*!\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 10 - #define U_PLANE_INACTIVITY_VALUE 0 /* defined 10ms order (zero means infinity) */ @@ -543,7 +540,6 @@ typedef enum { SCHED_MODE_FAIR_RR /// fair raund robin } SCHEDULER_MODES; - /*! \brief temporary struct for ULSCH sched */ typedef struct { rnti_t rnti; @@ -1150,9 +1146,6 @@ typedef struct { 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]; } UE_info_t; /*! \brief deleting control information*/ @@ -1171,101 +1164,6 @@ typedef struct { int tail_freelist; ///the tail position of the delete list } UE_free_list_t; -/** - * slice specific scheduler for the DL - */ -typedef void (*slice_scheduler_dl)(module_id_t mod_id, - int slice_idx, - frame_t frame, - sub_frame_t subframe, - int *mbsfn_flag); - -typedef struct { - slice_id_t id; - - /// RB share for each slice - float pct; - - /// whether this slice is isolated from the others - int isol; - - int prio; - - /// Frequency ranges for slice positioning - int pos_low; - int pos_high; - - // max mcs for each slice - int maxmcs; - - /// criteria for sorting policies of the slices - uint32_t sorting; - - /// Accounting policy (just greedy(1) or fair(0) setting for now) - int accounting; - - /// name of available scheduler - char *sched_name; - - /// pointer to the slice specific scheduler in DL - slice_scheduler_dl sched_cb; - -} slice_sched_conf_dl_t; - -typedef void (*slice_scheduler_ul)(module_id_t mod_id, - int slice_idx, - frame_t frame, - sub_frame_t subframe, - unsigned char sched_subframe, - uint16_t *first_rb); - -typedef struct { - slice_id_t id; - - /// RB share for each slice - float pct; - - // MAX MCS for each slice - int maxmcs; - - /// criteria for sorting policies of the slices - uint32_t sorting; - - /// starting RB (RB offset) of UL scheduling - int first_rb; - - /// name of available scheduler - char *sched_name; - - /// pointer to the slice specific scheduler in UL - slice_scheduler_ul sched_cb; - -} slice_sched_conf_ul_t; - - -typedef struct { - /// counter used to indicate when all slices have pre-allocated UEs - //int slice_counter; - - /// indicates whether remaining RBs after first intra-slice allocation will - /// be allocated to UEs of the same slice - int intraslice_share_active; - /// indicates whether remaining RBs after slice allocation will be - /// allocated to UEs of another slice. Isolated slices will be ignored - int interslice_share_active; - - /// number of active DL slices - int n_dl; - slice_sched_conf_dl_t dl[MAX_NUM_SLICES]; - - /// number of active UL slices - int n_ul; - slice_sched_conf_ul_t ul[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 */ @@ -1274,6 +1172,82 @@ typedef struct { int length; } contig_rbs_t; +/** + * definition of a scheduling algorithm implementation used in the + * default DL scheduler + */ +typedef struct { + char *name; + void *(*setup)(void); + void (*unset)(void **); + int (*run)( + module_id_t, int, int, int, UE_list_t *, int, int, uint8_t *, void *); + void *data; +} default_sched_dl_algo_t; + +/** + * definition of a scheduling algorithm implementation used in the + * default UL scheduler + */ +typedef struct { + char *name; + void *(*setup)(void); + void (*unset)(void **); + int (*run)( + module_id_t, int, int, int, int, int, UE_list_t *, int, int, contig_rbs_t *, void *); + void *data; +} default_sched_ul_algo_t; + +typedef void (*pp_impl_dl)(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe); +typedef void (*pp_impl_ul)(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe, + frame_t sched_frame, + sub_frame_t sched_subframe); + +struct slice_info_s; +typedef struct { + int algorithm; + + /// inform the slice algorithm about a new UE + void (*add_UE)(struct slice_info_s *s, int UE_id); + /// inform the slice algorithm about a UE that disconnected + void (*remove_UE)(struct slice_info_s *s, int UE_id); + /// move a UE to a slice in DL/UL, -1 means don't move (no-op). + void (*move_UE)(struct slice_info_s *s, int UE_id, int idx); + + /// Adds a new slice through admission control. slice_params are + /// algorithm-specific parameters. sched is either a default_sched_ul_algo_t + /// or default_sched_dl_algo_t, depending on whether this implementation + /// handles UL/DL. If slice at index exists, updates existing + /// slice. Returns index of new slice or -1 on failure. + int (*addmod_slice)(struct slice_info_s *s, + int id, + char *label, + void *sched, + void *slice_params); + /// Returns slice through slice_idx. 1 if successful, 0 if not. + int (*remove_slice)(struct slice_info_s *s, uint8_t slice_idx); + + union { + pp_impl_dl dl; + pp_impl_ul ul; + }; + + union { + default_sched_ul_algo_t ul_algo; + default_sched_dl_algo_t dl_algo; + }; + + void (*destroy)(struct slice_info_s **s); + + struct slice_info_s *slices; +} pp_impl_param_t; + /*! \brief eNB common channels */ typedef struct { int physCellId; @@ -1395,9 +1369,6 @@ typedef struct eNB_MAC_INST_s { uint32_t ul_handle; UE_info_t UE_info; - /// slice-related configuration - slice_info_t slice_info; - ///subband bitmap configuration SBMAP_CONF sbmap_conf; /// CCE table used to build DCI scheduling information @@ -1432,6 +1403,11 @@ typedef struct eNB_MAC_INST_s { UE_free_list_t UE_free_list; /// for scheduling selection SCHEDULER_MODES scheduler_mode; + /// Default scheduler: Pre-processor implementation. Algorithms for UL/DL + /// are called by ULSCH/DLSCH, respectively. Pro-processor implementation can + /// encapsulate slicing. + pp_impl_param_t pre_processor_dl; + pp_impl_param_t pre_processor_ul; int32_t puSch10xSnr; int32_t puCch10xSnr; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 2cb86c25af..9d49fdffd5 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -187,8 +187,6 @@ void add_msg3(module_id_t module_idP, int CC_id, RA_t *ra, frame_t frameP, void init_UE_info(UE_info_t *UE_info); -void init_slice_info(slice_info_t *sli); - int mac_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active); @@ -661,6 +659,7 @@ 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); +void init_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); @@ -675,10 +674,10 @@ void set_ul_DAI(int module_idP, void ulsch_scheduler_pre_processor(module_id_t module_idP, int CC_id, - int frameP, + frame_t frameP, sub_frame_t subframeP, - int sched_frameP, - unsigned char sched_subframeP); + frame_t sched_frameP, + sub_frame_t sched_subframeP); int phy_stats_exist(module_id_t Mod_id, int rnti); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 1a88623a1f..af6d1a7ac3 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -45,11 +45,8 @@ extern RAN_CONTEXT_t RC; void init_UE_info(UE_info_t *UE_info) { - int list_el; 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; + init_ue_list(&UE_info->list); 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)); @@ -57,32 +54,6 @@ void init_UE_info(UE_info_t *UE_info) memset(UE_info->active, 0, sizeof(UE_info->active)); } -void init_slice_info(slice_info_t *sli) -{ - sli->intraslice_share_active = 1; - sli->interslice_share_active = 1; - - sli->n_dl = 1; - memset(sli->dl, 0, sizeof(slice_sched_conf_dl_t) * MAX_NUM_SLICES); - sli->dl[0].pct = 1.0; - sli->dl[0].prio = 10; - sli->dl[0].pos_high = N_RBG_MAX; - sli->dl[0].maxmcs = 28; - sli->dl[0].sorting = 0x012345; - sli->dl[0].sched_name = "schedule_ue_spec"; - sli->dl[0].sched_cb = dlsym(NULL, sli->dl[0].sched_name); - AssertFatal(sli->dl[0].sched_cb, "DLSCH scheduler callback is NULL\n"); - - sli->n_ul = 1; - memset(sli->ul, 0, sizeof(slice_sched_conf_ul_t) * MAX_NUM_SLICES); - sli->ul[0].pct = 1.0; - sli->ul[0].maxmcs = 20; - sli->ul[0].sorting = 0x0123; - sli->ul[0].sched_name = "schedule_ulsch_rnti"; - sli->ul[0].sched_cb = dlsym(NULL, sli->ul[0].sched_name); - AssertFatal(sli->ul[0].sched_cb, "ULSCH scheduler callback is NULL\n"); -} - void mac_top_init_eNB(void) { module_id_t i, j; @@ -129,8 +100,23 @@ void mac_top_init_eNB(void) mac[i]->if_inst = IF_Module_init(i); + mac[i]->pre_processor_dl.algorithm = 0; + mac[i]->pre_processor_dl.dl = dlsch_scheduler_pre_processor; + char *s = "round_robin_dl"; + void *d = dlsym(NULL, s); + AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); + mac[i]->pre_processor_dl.dl_algo = *(default_sched_dl_algo_t *) d; + mac[i]->pre_processor_dl.dl_algo.data = mac[i]->pre_processor_dl.dl_algo.setup(); + + mac[i]->pre_processor_ul.algorithm = 0; + mac[i]->pre_processor_ul.ul = ulsch_scheduler_pre_processor; + s = "round_robin_ul"; + d = dlsym(NULL, s); + AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); + mac[i]->pre_processor_ul.ul_algo = *(default_sched_ul_algo_t *) d; + mac[i]->pre_processor_ul.ul_algo.data = mac[i]->pre_processor_ul.ul_algo.setup(); + init_UE_info(&mac[i]->UE_info); - init_slice_info(&mac[i]->slice_info); } RC.mac = mac; diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 4f3baf1783..6477d60021 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -69,31 +69,367 @@ int get_rbg_size_last(module_id_t Mod_id, int CC_id) { 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) { +void *rr_dl_setup(void) { + void *data = malloc(sizeof(int)); + *(int *) data = 0; + AssertFatal(data, "could not allocate data in %s()\n", __func__); + return data; +} +void rr_dl_unset(void **data) { + if (*data) + free(*data); + *data = NULL; +} +int rr_dl_run(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, + void *data) { 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. + /* just start with the UE after the one we had last time. If it does not + * exist, this will start at the head */ + int *start_ue = data; + *start_ue = next_ue_list_looped(UE_list, *start_ue); + + int UE_id = *start_ue; + UE_list_t UE_sched; + int *cur_UE = &UE_sched.head; + // Allocate retransmissions, and mark UEs with new transmissions + do { + // 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) + goto skip_ue; + 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); + goto skip_ue; + } + // 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); + goto skip_ue; + } + 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) + goto skip_ue; // 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; + rbgalloc_mask[rbg] = 0; + 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 { + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) { + *cur_UE = UE_id; + cur_UE = &UE_sched.next[UE_id]; + } + } + +skip_ue: + UE_id = next_ue_list_looped(UE_list, UE_id); + } while (UE_id != *start_ue); + *cur_UE = -1; // mark end + + if (UE_sched.head < 0) + return n_rbg_sched; // no UE has a transmission + + // after allocating retransmissions: pre-allocate CCE, compute number of + // requested RBGs + max_num_ue = min(max_num_ue, n_rbg_sched); + int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request + cur_UE = &UE_sched.head; + while (*cur_UE >= 0 && max_num_ue > 0) { + const int UE_id = *cur_UE; + cur_UE = &UE_sched.next[UE_id]; // go to next + 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); + continue; + } + UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; + const int mcs = cqi_to_mcs[cqi]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; + const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total; + rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize); + max_num_ue--; + } + *cur_UE = -1; // not all UEs might be allocated, mark end + + /* for one UE after the next: allocate resources */ + cur_UE = &UE_sched.head; + while (*cur_UE >= 0) { + const int UE_id = *cur_UE; + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; + ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; + rb_required[UE_id] -= sRBG; + if (rb_required[UE_id] <= 0) { + *cur_UE = UE_sched.next[*cur_UE]; + if (*cur_UE < 0) + cur_UE = &UE_sched.head; + } else { + cur_UE = UE_sched.next[*cur_UE] < 0 ? &UE_sched.head : &UE_sched.next[*cur_UE]; + } + n_rbg_sched--; + if (n_rbg_sched <= 0) + break; + for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } + + return n_rbg_sched; +} +default_sched_dl_algo_t round_robin_dl = { + .name = "round_robin_dl", + .setup = rr_dl_setup, + .unset = rr_dl_unset, + .run = rr_dl_run, + .data = NULL +}; + + +void *pf_dl_setup(void) { + void *data = calloc(MAX_MOBILES_PER_ENB, sizeof(float)); + for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) + *(float *) data = 0.0f; + AssertFatal(data, "could not allocate data in %s()\n", __func__); + return data; +} +void pf_dl_unset(void **data) { + if (*data) + free(*data); + *data = NULL; +} +int pf_wbcqi_dl_run(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, + void *data) { + 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); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + + int rbg = 0; + for (; !rbgalloc_mask[rbg]; rbg++) + ; /* fast-forward to first allowed RBG */ + + UE_list_t UE_sched; // UEs that could be scheduled + int *uep = &UE_sched.head; + float *thr_ue = data; + float coeff_ue[MAX_MOBILES_PER_ENB]; + + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + const float a = 0.0005f; // corresponds to 200ms window + const uint32_t b = UE_info->eNB_UE_stats[CC_id][UE_id].TBS; + thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b; + + // 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; + rbgalloc_mask[rbg] = 0; + 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 { + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) + continue; + + const int mcs = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + const uint32_t tbs = get_TBS_DL(mcs, RBGsize); + coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id]; + //LOG_I(MAC, " pf UE %d: old TBS %d thr %f MCS %d TBS %d coeff %f\n", + // UE_id, b, thr_ue[UE_id], mcs, tbs, coeff_ue[UE_id]); + *uep = UE_id; + uep = &UE_sched.next[UE_id]; + } + } + *uep = -1; + + while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) { + int *max = &UE_sched.head; /* assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* if the current one has larger coeff, save for later */ + if (coeff_ue[*p] > coeff_ue[*max]) + max = p; + p = &UE_sched.next[*p]; + } + /* remove the max one */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; + + 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) + continue; + UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; + + max_num_ue--; + + /* allocate as much as possible */ + const int mcs = cqi_to_mcs[cqi]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; + int req = find_nb_rb_DL(mcs, + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, + n_rbg_sched * RBGsize, + RBGsize); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + while (req > 0 && n_rbg_sched > 0) { + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; + ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; + req -= sRBG; + n_rbg_sched--; + for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } + } + + return n_rbg_sched; +} +default_sched_dl_algo_t proportional_fair_wbcqi_dl = { + .name = "proportional_fair_wbcqi_dl", + .setup = pf_dl_setup, + .unset = pf_dl_unset, + .run = pf_wbcqi_dl_run, + .data = NULL +}; + +void *mt_dl_setup(void) { + return NULL; +} +void mt_dl_unset(void **data) { + *data = NULL; +} +int mt_wbcqi_dl_run(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, + void *data) { + 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); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + + int rbg = 0; + for (; !rbgalloc_mask[rbg]; rbg++) + ; /* fast-forward to first allowed RBG */ + + UE_list_t UE_sched; // UEs that could be scheduled + int *uep = &UE_sched.head; + 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]; @@ -133,6 +469,7 @@ int round_robin_dl(module_id_t Mod_id, if (!rbgalloc_mask[rbg]) continue; ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; nb_rbg--; } LOG_D(MAC, @@ -150,90 +487,69 @@ int round_robin_dl(module_id_t Mod_id, 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_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) + continue; + *uep = UE_id; + uep = &UE_sched.next[UE_id]; } } + *uep = -1; - if (num_ue_req == 0) - return n_rbg_sched; // no UE has a transmission + while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) { + int *max = &UE_sched.head; /* assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* if the current one has better CQI, or the same and more data */ + const uint8_t maxCqi = UE_info->UE_sched_ctrl[*max].dl_cqi[CC_id]; + const uint32_t maxB = UE_info->UE_template[CC_id][*max].dl_buffer_total; + const uint8_t pCqi = UE_info->UE_sched_ctrl[*p].dl_cqi[CC_id]; + const uint32_t pB = UE_info->UE_template[CC_id][*p].dl_buffer_total; + if (pCqi > maxCqi || (pCqi == maxCqi && pB > maxB)) + max = p; + p = &UE_sched.next[*p]; + } + /* remove the max one */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; - // 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 + if (idx < 0) 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 - } - *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; + max_num_ue--; + + /* allocate as much as possible */ + const int mcs = cqi_to_mcs[cqi]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; + int req = find_nb_rb_DL(mcs, + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, + n_rbg_sched * RBGsize, + RBGsize); 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 */ ; - } - - /* 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); + while (req > 0 && n_rbg_sched > 0) { + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; + ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; + req -= sRBG; + n_rbg_sched--; + for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } } return n_rbg_sched; } +default_sched_dl_algo_t maximum_throughput_wbcqi_dl = { + .name = "maximum_throughput_wbcqi_dl", + .setup = mt_dl_setup, + .unset = mt_dl_unset, + .run = mt_wbcqi_dl_run, + .data = NULL +}; // This function stores the downlink buffer for all the logical channels void @@ -323,19 +639,18 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, frame_t frameP, 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); + eNB_MAC_INST *mac = RC.mac[Mod_id]; + UE_info_t *UE_info = &mac->UE_info; + const int N_RBG = to_rbg(mac->common_channels[CC_id].mib->message.dl_Bandwidth); const int RBGsize = get_min_rb_unit(Mod_id, CC_id); store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP); 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 *cur = &UE_to_sched.head; - 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]; @@ -368,20 +683,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, } /* define UEs to schedule */ - if (first) { - first = 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; + *cur = UE_id; + cur = &UE_to_sched.next[UE_id]; } + *cur = -1; if (UE_to_sched.head < 0) return; - uint8_t *vrb_map = RC.mac[Mod_id]->common_channels[CC_id].vrb_map; + uint8_t *vrb_map = mac->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++) { @@ -393,14 +703,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, n_rbg_sched += rbgalloc_mask[i]; } - round_robin_dl(Mod_id, - CC_id, - frameP, - subframeP, - &UE_to_sched, - 4, // max_num_ue - n_rbg_sched, - rbgalloc_mask); + mac->pre_processor_dl.dl_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + &UE_to_sched, + 4, // max_num_ue + n_rbg_sched, + rbgalloc_mask, + mac->pre_processor_dl.dl_algo.data); // 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 @@ -512,17 +823,28 @@ int pp_find_rb_table_index(int approximate) { 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) { +void *rr_ul_setup(void) { + void *data = malloc(sizeof(int)); + *(int *) data = 0; + AssertFatal(data, "could not allocate data in %s()\n", __func__); + return data; +} +void rr_ul_unset(void **data) { + if (*data) + free(*data); + *data = NULL; +} +int rr_ul_run(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, + void *data) { 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; @@ -662,9 +984,10 @@ int round_robin_ul(module_id_t Mod_id, 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 *start_ue = data; + if (*start_ue == -1) + *start_ue = UE_list->head; + int sUE_id = *start_ue; int rb_idx_given[MAX_MOBILES_PER_ENB]; memset(rb_idx_given, 0, sizeof(rb_idx_given)); @@ -742,35 +1065,35 @@ int round_robin_ul(module_id_t Mod_id, } } - /* 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); - } + /* just start with the next UE next time */ + *start_ue = next_ue_list_looped(UE_list, *start_ue); return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); } +default_sched_ul_algo_t round_robin_ul = { + .name = "round_robin_ul", + .setup = rr_ul_setup, + .unset = rr_ul_unset, + .run = rr_ul_run, + .data = NULL +}; void ulsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, - int frameP, + frame_t frameP, sub_frame_t subframeP, - int sched_frameP, - 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]; + frame_t sched_frameP, + sub_frame_t sched_subframeP) { + eNB_MAC_INST *mac = RC.mac[Mod_id]; + UE_info_t *UE_info = &mac->UE_info; + const int N_RB_UL = to_prb(mac->common_channels[CC_id].ul_Bandwidth); + COMMON_channels_t *cc = &mac->common_channels[CC_id]; 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 *cur = &UE_to_sched.head; - 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]; @@ -793,13 +1116,10 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, 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; + *cur = UE_id; + cur = &UE_to_sched.next[UE_id]; } + *cur = -1; if (UE_to_sched.head < 0) return; @@ -820,16 +1140,17 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, } } - round_robin_ul(Mod_id, - CC_id, - frameP, - subframeP, - sched_frameP, - sched_subframeP, - &UE_to_sched, - 4, // max_num_ue - n_contig, - rbs); + mac->pre_processor_ul.ul_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + sched_frameP, + sched_subframeP, + &UE_to_sched, + 4, // max_num_ue + n_contig, + rbs, + mac->pre_processor_ul.ul_algo.data); // 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 @@ -848,7 +1169,7 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, continue; print = 1; - uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id], + uint8_t harq_pid = subframe2harqpid(&mac->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, diff --git a/openair2/LAYER2/MAC/slicing/slicing.c b/openair2/LAYER2/MAC/slicing/slicing.c new file mode 100644 index 0000000000..9c88f6cffb --- /dev/null +++ b/openair2/LAYER2/MAC/slicing/slicing.c @@ -0,0 +1,601 @@ +/* + * 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 slicing.c + * \brief Generic slicing helper functions and Static Slicing Implementation + * \author Robert Schmidt + * \date 2020 + * \email robert.schmidt@eurecom.fr + */ + +#define _GNU_SOURCE +#include +#include + +#include "assertions.h" +#include "common/utils/LOG/log.h" + +#include "slicing.h" +#include "slicing_internal.h" + +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + +#define RET_FAIL(ret, x...) do { LOG_E(MAC, x); return ret; } while (0) + +int slicing_get_UE_slice_idx(slice_info_t *si, int UE_id) { + return si->UE_assoc_slice[UE_id]; +} + +void slicing_add_UE(slice_info_t *si, int UE_id) { + add_ue_list(&si->s[0]->UEs, UE_id); + si->UE_assoc_slice[UE_id] = 0; +} + +void _remove_UE(slice_t **s, uint8_t *assoc, int UE_id) { + const uint8_t i = assoc[UE_id]; + DevAssert(remove_ue_list(&s[i]->UEs, UE_id)); + assoc[UE_id] = -1; +} + +void slicing_remove_UE(slice_info_t *si, int UE_id) { + _remove_UE(si->s, si->UE_assoc_slice, UE_id); +} + +void _move_UE(slice_t **s, uint8_t *assoc, int UE_id, int to) { + const uint8_t i = assoc[UE_id]; + const int ri = remove_ue_list(&s[i]->UEs, UE_id); + if (!ri) + LOG_W(MAC, "did not find UE %d in DL slice index %d\n", UE_id, i); + add_ue_list(&s[to]->UEs, UE_id); + assoc[UE_id] = to; +} + +void slicing_move_UE(slice_info_t *si, int UE_id, int idx) { + DevAssert(idx >= -1 && idx < si->num); + if (idx >= 0) + _move_UE(si->s, si->UE_assoc_slice, UE_id, idx); +} + +int _exists_slice(uint8_t n, slice_t **s, int id) { + for (int i = 0; i < n; ++i) + if (s[i]->id == id) + return i; + return -1; +} + +slice_t *_add_slice(uint8_t *n, slice_t **s) { + s[*n] = calloc(1, sizeof(slice_t)); + if (!s[*n]) + return NULL; + init_ue_list(&s[*n]->UEs); + *n += 1; + return s[*n - 1]; +} + +slice_t *_remove_slice(uint8_t *n, slice_t **s, uint8_t *assoc, int idx) { + if (idx >= *n) + return NULL; + + slice_t *sr = s[idx]; + while (sr->UEs.head >= 0) + _move_UE(s, assoc, sr->UEs.head, 0); + + for (int i = idx + 1; i < *n; ++i) + s[i - 1] = s[i]; + *n -= 1; + s[*n] = NULL; + + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + if (assoc[i] > idx) + assoc[i] -= 1; + + if (sr->label) + free(sr->label); + + return sr; +} + +/************************ Static Slicing Implementation ************************/ + +int addmod_static_slice_dl(slice_info_t *si, + int id, + char *label, + void *algo, + void *slice_params_dl) { + static_slice_param_t *dl = slice_params_dl; + if (dl && dl->posLow > dl->posHigh) + RET_FAIL(-1, "%s(): slice id %d posLow > posHigh\n", __func__, id); + + uint8_t rbgMap[25] = { 0 }; + int index = _exists_slice(si->num, si->s, id); + if (index >= 0) { + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *sd = dl && si->s[s]->id == id ? dl : si->s[s]->algo_data; + for (int i = sd->posLow; i <= sd->posHigh; ++i) { + if (rbgMap[i]) + RET_FAIL(-33, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + rbgMap[i] = 1; + } + } + /* no problem, can allocate */ + slice_t *s = si->s[index]; + if (label) { + if (s->label) free(s->label); + s->label = label; + } + if (algo) { + s->dl_algo.unset(&s->dl_algo.data); + s->dl_algo = *(default_sched_dl_algo_t *) algo; + if (!s->dl_algo.data) + s->dl_algo.data = s->dl_algo.setup(); + } + if (dl) { + free(s->algo_data); + s->algo_data = dl; + } + return index; + } + + if (!dl) + RET_FAIL(-100, "%s(): no parameters for new slice %d, aborting\n", __func__, id); + + if (si->num >= MAX_STATIC_SLICES) + RET_FAIL(-2, "%s(): cannot have more than %d slices\n", __func__, MAX_STATIC_SLICES); + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *sd = si->s[s]->algo_data; + for (int i = sd->posLow; i <= sd->posHigh; ++i) + rbgMap[i] = 1; + } + + for (int i = dl->posLow; i <= dl->posHigh; ++i) + if (rbgMap[i]) + RET_FAIL(-3, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + + if (!algo) + RET_FAIL(-14, "%s(): no scheduler algorithm provided\n", __func__); + + slice_t *ns = _add_slice(&si->num, si->s); + if (!ns) + RET_FAIL(-4, "%s(): could not create new slice\n", __func__); + ns->id = id; + ns->label = label; + ns->dl_algo = *(default_sched_dl_algo_t *) algo; + if (!ns->dl_algo.data) + ns->dl_algo.data = ns->dl_algo.setup(); + ns->algo_data = dl; + + return si->num - 1; +} + +int addmod_static_slice_ul(slice_info_t *si, + int id, + char *label, + void *algo, + void *slice_params_ul) { + static_slice_param_t *ul = slice_params_ul; + /* Minimum 3RBs, because LTE stack requires this */ + if (ul && ul->posLow + 2 > ul->posHigh) + RET_FAIL(-1, "%s(): slice id %d posLow + 2 > posHigh\n", __func__, id); + + uint8_t rbMap[110] = { 0 }; + int index = _exists_slice(si->num, si->s, id); + if (index >= 0) { + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *su = ul && si->s[s]->id == id && ul ? ul : si->s[s]->algo_data; + for (int i = su->posLow; i <= su->posHigh; ++i) { + if (rbMap[i]) + RET_FAIL(-33, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + rbMap[i] = 1; + } + } + /* no problem, can allocate */ + slice_t *s = si->s[index]; + if (algo) { + s->ul_algo.unset(&s->ul_algo.data); + s->ul_algo = *(default_sched_ul_algo_t *) algo; + if (!s->ul_algo.data) + s->ul_algo.data = s->ul_algo.setup(); + } + if (label) { + if (s->label) free(s->label); + s->label = label; + } + if (ul) { + free(s->algo_data); + s->algo_data = ul; + } + return index; + } + + if (!ul) + RET_FAIL(-100, "%s(): no parameters for new slice %d, aborting\n", __func__, id); + + if (si->num >= MAX_STATIC_SLICES) + RET_FAIL(-2, "%s(): cannot have more than %d slices\n", __func__, MAX_STATIC_SLICES); + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *sd = si->s[s]->algo_data; + for (int i = sd->posLow; i <= sd->posHigh; ++i) + rbMap[i] = 1; + } + + for (int i = ul->posLow; i <= ul->posHigh; ++i) + if (rbMap[i]) + RET_FAIL(-3, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + + if (!algo) + RET_FAIL(-14, "%s(): no scheduler algorithm provided\n", __func__); + + slice_t *ns = _add_slice(&si->num, si->s); + if (!ns) + RET_FAIL(-4, "%s(): could not create new slice\n", __func__); + ns->id = id; + ns->label = label; + ns->ul_algo = *(default_sched_ul_algo_t *) algo; + if (!ns->ul_algo.data) + ns->ul_algo.data = ns->ul_algo.setup(); + ns->algo_data = ul; + + return si->num - 1; +} + +int remove_static_slice_dl(slice_info_t *si, uint8_t slice_idx) { + if (slice_idx == 0) + return 0; + slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx); + if (!sr) + return 0; + free(sr->algo_data); + sr->dl_algo.unset(&sr->dl_algo.data); + free(sr); + return 1; +} + +int remove_static_slice_ul(slice_info_t *si, uint8_t slice_idx) { + if (slice_idx == 0) + return 0; + slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx); + if (!sr) + return 0; + free(sr->algo_data); + sr->ul_algo.unset(&sr->ul_algo.data); + free(sr); + return 1; +} + +void static_dl(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe) { + UE_info_t *UE_info = &RC.mac[mod_id]->UE_info; + + store_dlsch_buffer(mod_id, CC_id, frame, subframe); + + 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]; + + /* 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 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); + uint8_t *vrb_map = RC.mac[mod_id]->common_channels[CC_id].vrb_map; + uint8_t rbgalloc_mask[N_RBG_MAX]; + 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]; + } + + slice_info_t *s = RC.mac[mod_id]->pre_processor_dl.slices; + int max_num_ue; + switch (s->num) { + case 1: + max_num_ue = 4; + break; + case 2: + max_num_ue = 2; + break; + default: + max_num_ue = 1; + break; + } + for (int i = 0; i < s->num; ++i) { + if (s->s[i]->UEs.head < 0) + continue; + uint8_t rbgalloc_slice_mask[N_RBG_MAX]; + memset(rbgalloc_slice_mask, 0, sizeof(rbgalloc_slice_mask)); + static_slice_param_t *p = s->s[i]->algo_data; + int n_rbg_sched = 0; + for (int rbg = p->posLow; rbg <= p->posHigh && rbg <= N_RBG; ++rbg) { + rbgalloc_slice_mask[rbg] = rbgalloc_mask[rbg]; + n_rbg_sched += rbgalloc_mask[rbg]; + } + + s->s[i]->dl_algo.run(mod_id, + CC_id, + frame, + subframe, + &s->s[i]->UEs, + max_num_ue, // max_num_ue + n_rbg_sched, + rbgalloc_slice_mask, + s->s[i]->dl_algo.data); + } + + // 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 + 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]; + + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) + continue; + + LOG_D(MAC, + "%4d.%d UE%d %d RBs allocated, pre MCS %d\n", + frame, + subframe, + UE_id, + ue_sched_ctrl->pre_nb_available_rbs[CC_id], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1); + + print = 1; + + for (int i = 0; i < N_RBG; i++) { + if (!ue_sched_ctrl->rballoc_sub_UE[CC_id][i]) + continue; + 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", frame, subframe, t); + LOG_E(MAC, "%4d.%d: UE %d allocated at locked RB %d/RBG %d\n", frame, + subframe, UE_id, RBGsize * i + j, i); + } + vrb_map[RBGsize*i+j] = 1; + } + t[i] = '0' + UE_id; + } + } + if (print) + LOG_D(MAC, "%4d.%d DL scheduler allocation list: %s\n", frame, subframe, t); +} + +void static_ul(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe, + frame_t sched_frame, + sub_frame_t sched_subframe) { + 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 (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_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; + } + + slice_info_t *s = RC.mac[mod_id]->pre_processor_ul.slices; + int max_num_ue; + switch (s->num) { + case 1: + max_num_ue = 4; + break; + case 2: + max_num_ue = 2; + break; + default: + max_num_ue = 1; + break; + } + for (int i = 0; i < s->num; ++i) { + if (s->s[i]->UEs.head < 0) + continue; + int last_rb_blocked = 1; + int n_contig = 0; + contig_rbs_t rbs[2]; // up to two contig RBs for PRACH in between + static_slice_param_t *p = s->s[i]->algo_data; + for (int rb = p->posLow; rb <= p->posHigh && rb < N_RB_UL; ++rb) { + if (cc->vrb_map_UL[rb] == 0 && last_rb_blocked) { + last_rb_blocked = 0; + n_contig++; + AssertFatal(n_contig <= 2, "cannot handle more than two contiguous RB regions\n"); + rbs[n_contig - 1].start = rb; + } + if (cc->vrb_map_UL[rb] == 1 && !last_rb_blocked) { + last_rb_blocked = 1; + rbs[n_contig - 1].length = rb - rbs[n_contig - 1].start; + } + } + if (!last_rb_blocked) + rbs[n_contig - 1].length = p->posHigh - rbs[n_contig - 1].start + 1; + + s->s[i]->ul_algo.run(mod_id, + CC_id, + frame, + subframe, + sched_frame, + sched_subframe, + &s->s[i]->UEs, + max_num_ue, // max_num_ue + n_contig, + rbs, + s->s[i]->ul_algo.data); + } + + // 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 + 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; + + print = 1; + uint8_t harq_pid = subframe2harqpid(&RC.mac[mod_id]->common_channels[CC_id], + sched_frame, sched_subframe); + LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n", + frame, + subframe, + 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 (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) { + + LOG_I(MAC, "%4d.%d UL scheduler allocation list: %s\n", frame, subframe, t); + LOG_E(MAC, + "%4d.%d: UE %d allocated at locked RB %d (is: allocated start " + "%d/length %d)\n", + frame, subframe, 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'; + } + } + if (print) + LOG_D(MAC, + "%4d.%d UL scheduler allocation list: %s\n", + sched_frame, + sched_subframe, + t); +} + +void static_destroy(slice_info_t **si) { + const int n = (*si)->num; + (*si)->num = 0; + for (int i = 0; i < n; ++i) { + slice_t *s = (*si)->s[i]; + if (s->label) + free(s->label); + free(s->algo_data); + free(s); + } + free((*si)->s); + free(*si); +} + +pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id) { + slice_info_t *si = calloc(1, sizeof(slice_info_t)); + DevAssert(si); + + si->num = 0; + si->s = calloc(MAX_STATIC_SLICES, sizeof(slice_t)); + DevAssert(si->s); + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + si->UE_assoc_slice[i] = -1; + + /* insert default slice, all resources */ + static_slice_param_t *dlp = malloc(sizeof(static_slice_param_t)); + dlp->posLow = 0; + dlp->posHigh = to_rbg(RC.mac[mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth) - 1; + default_sched_dl_algo_t *algo = &RC.mac[mod_id]->pre_processor_dl.dl_algo; + algo->data = NULL; + DevAssert(0 == addmod_static_slice_dl(si, 0, strdup("default"), algo, dlp)); + const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) + slicing_add_UE(si, UE_id); + + pp_impl_param_t sttc; + sttc.algorithm = STATIC_SLICING; + sttc.add_UE = slicing_add_UE; + sttc.remove_UE = slicing_remove_UE; + sttc.move_UE = slicing_move_UE; + sttc.addmod_slice = addmod_static_slice_dl; + sttc.remove_slice = remove_static_slice_dl; + sttc.dl = static_dl; + // current DL algo becomes default scheduler + sttc.dl_algo = *algo; + sttc.destroy = static_destroy; + sttc.slices = si; + + return sttc; +} + +pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id) { + slice_info_t *si = calloc(1, sizeof(slice_info_t)); + DevAssert(si); + + si->num = 0; + si->s = calloc(MAX_STATIC_SLICES, sizeof(slice_t)); + DevAssert(si->s); + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + si->UE_assoc_slice[i] = -1; + + /* insert default slice, all resources */ + static_slice_param_t *ulp = malloc(sizeof(static_slice_param_t)); + ulp->posLow = 0; + ulp->posHigh = to_prb(RC.mac[mod_id]->common_channels[CC_id].ul_Bandwidth) - 1; + default_sched_ul_algo_t *algo = &RC.mac[mod_id]->pre_processor_ul.ul_algo; + algo->data = NULL; + DevAssert(0 == addmod_static_slice_ul(si, 0, strdup("default"), algo, ulp)); + const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) + slicing_add_UE(si, UE_id); + + pp_impl_param_t sttc; + sttc.algorithm = STATIC_SLICING; + sttc.add_UE = slicing_add_UE; + sttc.remove_UE = slicing_remove_UE; + sttc.move_UE = slicing_move_UE; + sttc.addmod_slice = addmod_static_slice_ul; + sttc.remove_slice = remove_static_slice_ul; + sttc.ul = static_ul; + // current DL algo becomes default scheduler + sttc.ul_algo = *algo; + sttc.destroy = static_destroy; + sttc.slices = si; + + return sttc; +} diff --git a/openair2/LAYER2/MAC/slicing/slicing.h b/openair2/LAYER2/MAC/slicing/slicing.h new file mode 100644 index 0000000000..1099b50ea0 --- /dev/null +++ b/openair2/LAYER2/MAC/slicing/slicing.h @@ -0,0 +1,74 @@ +/* + * 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 slicing.h + * \brief General slice definition and helper parameters + * \author Robert Schmidt + * \date 2020 + * \email robert.schmidt@eurecom.fr + */ + +#ifndef __SLICING_H__ +#define __SLICING_H__ + +#include "openair2/LAYER2/MAC/mac.h" + +typedef struct slice_s { + /// Arbitrary ID + slice_id_t id; + /// Arbitrary label + char *label; + + union { + default_sched_dl_algo_t dl_algo; + default_sched_ul_algo_t ul_algo; + }; + + /// A specific algorithm's implementation parameters + void *algo_data; + /// Internal data that might be kept alongside a slice's params + void *int_data; + + // list of users in this slice + UE_list_t UEs; +} slice_t; + +typedef struct slice_info_s { + uint8_t num; + slice_t **s; + uint8_t UE_assoc_slice[MAX_MOBILES_PER_ENB]; +} slice_info_t; + +int slicing_get_UE_slice_idx(slice_info_t *si, int UE_id); + +#define STATIC_SLICING 10 +/* only four static slices for UL, DL resp. (not enough DCIs) */ +#define MAX_STATIC_SLICES 4 +typedef struct { + uint16_t posLow; + uint16_t posHigh; +} static_slice_param_t; +pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id); +pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id); + + +#endif /* __SLICING_H__ */ diff --git a/openair2/LAYER2/MAC/slicing/slicing_internal.h b/openair2/LAYER2/MAC/slicing/slicing_internal.h new file mode 100644 index 0000000000..744f8924d9 --- /dev/null +++ b/openair2/LAYER2/MAC/slicing/slicing_internal.h @@ -0,0 +1,46 @@ +/* + * 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 slicing_internal.h + * \brief Internal slice helper functions + * \author Robert Schmidt + * \date 2020 + * \email robert.schmidt@eurecom.fr + */ + +#ifndef __SLICING_INTERNAL_H__ +#define __SLICING_INTERNAL_H__ + +#include "slicing.h" + +void slicing_add_UE(slice_info_t *si, int UE_id); + +void _remove_UE(slice_t **s, uint8_t *assoc, int UE_id); +void slicing_remove_UE(slice_info_t *si, int UE_id); + +void _move_UE(slice_t **s, uint8_t *assoc, int UE_id, int to); +void slicing_move_UE(slice_info_t *si, int UE_id, int idx); + +slice_t *_add_slice(uint8_t *n, slice_t **s); +slice_t *_remove_slice(uint8_t *n, slice_t **s, uint8_t *assoc, int idx); + +#endif /* __SLICING_INTERNAL_H__ */ diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 5a9620ed01..bc98e16d39 100755 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -34,7 +34,6 @@ #include "NR_MAC_UE/mac_proto.h" #include "NR_MAC-CellGroupConfig.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" -#include "SCHED_NR/phy_frame_config_nr.h" int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu, @@ -326,6 +325,84 @@ void config_common_ue(NR_UE_MAC_INST_t *mac, } +/** \brief This function is relavant for the UE procedures for control. It loads the search spaces, the BWPs and the CORESETs into the MAC instance and + \brief performs assert checks on the relevant RRC configuration. + @param NR_UE_MAC_INST_t mac: pointer to local MAC instance + @returns void + */ +void config_control_ue(NR_UE_MAC_INST_t *mac){ + + uint8_t bwp_id = 1, coreset_id = 1, ss_id; + NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; + AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n"); + AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count); + + NR_BWP_DownlinkCommon_t *bwp_Common = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Common; + AssertFatal(bwp_Common != NULL, "bwp_Common is null\n"); + + NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Dedicated; + AssertFatal(dl_bwp_Dedicated != NULL, "dl_bwp_Dedicated is null\n"); + + NR_SetupRelease_PDCCH_Config_t *pdcch_Config = dl_bwp_Dedicated->pdcch_Config; + AssertFatal(pdcch_Config != NULL, "pdcch_Config is null\n"); + + NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; + AssertFatal(pdcch_ConfigCommon != NULL, "pdcch_ConfigCommon is null\n"); + AssertFatal(pdcch_ConfigCommon->choice.setup->ra_SearchSpace != NULL, "ra_SearchSpace must be available in DL BWP\n"); + + struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; + AssertFatal(commonSearchSpaceList != NULL, "commonSearchSpaceList is null\n"); + AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH CSS list has 0 elements\n"); + + struct NR_PDCCH_Config__controlResourceSetToAddModList *controlResourceSetToAddModList = pdcch_Config->choice.setup->controlResourceSetToAddModList; + AssertFatal(controlResourceSetToAddModList != NULL, "controlResourceSetToAddModList is null\n"); + AssertFatal(controlResourceSetToAddModList->list.count == 1, "controlResourceSetToAddModList->list.count=%d\n", controlResourceSetToAddModList->list.count); + AssertFatal(controlResourceSetToAddModList->list.array[0] != NULL, "coreset[0][0] is null\n"); + + struct NR_PDCCH_Config__searchSpacesToAddModList *searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList; + AssertFatal(searchSpacesToAddModList != NULL, "searchSpacesToAddModList is null\n"); + AssertFatal(searchSpacesToAddModList->list.count > 0, "list of UE specifically configured Search Spaces is empty\n"); + AssertFatal(searchSpacesToAddModList->list.count < FAPI_NR_MAX_SS_PER_CORESET, "too many searchpaces per coreset %d\n", searchSpacesToAddModList->list.count); + + struct NR_UplinkConfig__uplinkBWP_ToAddModList *uplinkBWP_ToAddModList = scd->uplinkConfig->uplinkBWP_ToAddModList; + AssertFatal(uplinkBWP_ToAddModList != NULL, "uplinkBWP_ToAddModList is null\n"); + AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count); + + // check pdcch_Config, pdcch_ConfigCommon and DL BWP + mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]; + mac->coreset[bwp_id - 1][coreset_id - 1] = controlResourceSetToAddModList->list.array[0]; + + // Check dedicated UL BWP and pass to MAC + mac->ULbwp[0] = uplinkBWP_ToAddModList->list.array[0]; + AssertFatal(mac->ULbwp[0]->bwp_Dedicated != NULL, "UL bwp_Dedicated is null\n"); + + // check available Search Spaces in the searchSpacesToAddModList and pass to MAC + // note: the network configures at most 10 Search Spaces per BWP per cell (including UE-specific and common Search Spaces). + for (ss_id = 0; ss_id < searchSpacesToAddModList->list.count; ss_id++) { + NR_SearchSpace_t *ss = searchSpacesToAddModList->list.array[ss_id]; + AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); + AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n"); + AssertFatal(*ss->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); + AssertFatal(ss->monitoringSymbolsWithinSlot != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot is null\n"); + AssertFatal(ss->monitoringSymbolsWithinSlot->buf != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot->buf is null\n"); + mac->SSpace[0][0][ss_id] = ss; + } + + // Check available CSSs in the commonSearchSpaceList (list of additional common search spaces) + // note: commonSearchSpaceList SIZE(1..4) + for (int css_id = 0; css_id < commonSearchSpaceList->list.count; css_id++) { + NR_SearchSpace_t *css = commonSearchSpaceList->list.array[css_id]; + AssertFatal(css->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); + AssertFatal(*css->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); + AssertFatal(css->searchSpaceId != 0, "css->searchSpaceId is 0\n"); + AssertFatal(css->searchSpaceType != NULL, "css->searchSpaceType is null\n"); + AssertFatal(css->monitoringSymbolsWithinSlot != NULL, "css->monitoringSymbolsWithinSlot is null\n"); + AssertFatal(css->monitoringSymbolsWithinSlot->buf != NULL, "css->monitoringSymbolsWithinSlot->buf is null\n"); + mac->SSpace[0][0][ss_id] = css; + ss_id++; + } +} + int nr_rrc_mac_config_req_ue( module_id_t module_id, int cc_idP, @@ -338,16 +415,16 @@ int nr_rrc_mac_config_req_ue( NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - // NR_ServingCellConfig_t *serving_cell_config = spcell_configP->spCellConfigDedicated; // TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc. - if(mibP != NULL){ mac->mib = mibP; // update by every reception } if(cell_group_config != NULL ){ + mac->scg = cell_group_config; mac->servCellIndex = *cell_group_config->spCellConfig->servCellIndex; + config_control_ue(mac); if (cell_group_config->spCellConfig->reconfigurationWithSync) { mac->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; @@ -355,7 +432,6 @@ int nr_rrc_mac_config_req_ue( mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti); } - mac->scg = cell_group_config; /* if(mac_cell_group_configP != NULL){ @@ -420,8 +496,8 @@ int nr_rrc_mac_config_req_ue( } } */ - } - + } + return 0; } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 5775e5bfb9..e45f6a9b69 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -178,7 +178,6 @@ typedef struct { SFN_C_TYPE type0_pdcch_ss_sfn_c; uint32_t type0_pdcch_ss_n_c; uint32_t type0_pdcch_consecutive_slots; - int rnti_type; /* PDUs */ /// Outgoing CCCH pdu for PHY @@ -222,11 +221,6 @@ typedef struct { uint32_t RA_tx_frame; /// Random-access variable for window calculation (subframe of last change in window counter) uint8_t RA_tx_subframe; - /// Scheduled RX frame for RA Msg2 - uint16_t msg2_rx_frame; - /// Scheduled RX slot for RA Msg2 - uint16_t msg2_rx_slot; - /// 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) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 56ae14f98b..351bcc292f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -62,9 +62,8 @@ #include "NR_MAC_COMMON/nr_mac.h" #include "LAYER2/NR_MAC_UE/mac_proto.h" -extern int64_t table_6_3_3_2_2_prachConfig_Index [256][9]; extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9]; -extern const uint16_t nr_slots_per_frame[5]; +extern const uint8_t nr_slots_per_frame[5]; //extern uint8_t nfapi_mode; @@ -360,11 +359,11 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, uint8_t sdu_lcids[NB_RB_MAX] = {0}; uint16_t sdu_lengths[NB_RB_MAX] = {0}; - int TBS_bytes = 848, header_length_total, num_sdus, offset, preambleTransMax, mac_ce_len; + int TBS_bytes = 848, header_length_total=0, num_sdus, offset, preambleTransMax, mac_ce_len; AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n"); - if (UE_mode == PRACH && prach_resources->init_msg1) { + if (UE_mode < PUSCH && prach_resources->init_msg1) { LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active); @@ -449,7 +448,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, nr_get_RA_window(mac); // Fill in preamble and PRACH resources - if (mac->generate_nr_prach) + if (mac->generate_nr_prach == 1) nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated); offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer @@ -471,7 +470,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, payload[offset + j] = 0; // mac_pdu[offset + j] = 0; } } - } else { // RACH is active + } else if (mac->RA_window_cnt != -1) { // RACH is active //////////////////////////////////////////////////////////////// /////* Random Access Response reception (5.1.4 TS 38.321) *///// @@ -482,7 +481,6 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // - handle beam failure recovery request // - handle DL assignment on PDCCH for RA-RNTI // - handle backoff and raResponseWindow params - // - disabled contention resolution as OAI NSA is contention-free based // LOG_D(MAC, "[MAC][UE %d][RAPROC] frame %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n", // mod_id, frame, nr_tti_tx, mac->RA_window_cnt, mac->RA_tx_frame, mac->RA_tx_subframe); @@ -495,12 +493,13 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, if (mac->RA_window_cnt >= 0 && mac->RA_RAPID_found == 1) { - // mac->ra_state = WAIT_CONTENTION_RESOLUTION; - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR successfully received \n", mod_id, frame, nr_tti_tx); + mac->RA_window_cnt = -1; + mac->ra_state = RA_SUCCEEDED; + LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR successfully received \n", mod_id, frame, nr_tti_tx); } else if (mac->RA_window_cnt == 0 && !mac->RA_RAPID_found) { - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR reception failed \n", mod_id, frame, nr_tti_tx); + LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception failed \n", mod_id, frame, nr_tti_tx); mac->ra_state = RA_UE_IDLE; mac->RA_PREAMBLE_TRANSMISSION_COUNTER++; @@ -572,21 +571,21 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources, // mac->RA_tx_subframe = nr_tti_tx; // Fill in preamble and PRACH resources - if (mac->generate_nr_prach) + if (mac->generate_nr_prach == 1) nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); } else { mac->RA_window_cnt--; - LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR reception not successful, (RA window count %d) \n", + LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception not successful, (RA window count %d) \n", mod_id, frame, nr_tti_tx, mac->RA_window_cnt); // Fill in preamble and PRACH resources - if (mac->generate_nr_prach) + if (mac->generate_nr_prach == 1) nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated); } @@ -616,28 +615,28 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac){ mac->RA_window_cnt = mac->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB switch (ra_ResponseWindow) { - case 0: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: mac->RA_window_cnt += 1; break; - case 1: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: mac->RA_window_cnt += 2; break; - case 2: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: mac->RA_window_cnt += 4; break; - case 3: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: mac->RA_window_cnt += 8; break; - case 4: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: mac->RA_window_cnt += 10; break; - case 5: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: mac->RA_window_cnt += 20; break; - case 6: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: mac->RA_window_cnt += 40; break; - case 7: + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: mac->RA_window_cnt += 80; break; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 53263747fc..2285fc5999 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -46,6 +46,8 @@ #endif #define LOG_DCI_PARM(a...) LOG_D(PHY,"\t<-NR_PDCCH_DCI_TOOLS_DEBUG (nr_generate_ue_ul_dlsch_params_from_dci)" a) +// #define DEBUG_DCI + dci_pdu_rel15_t *def_dci_pdu_rel15; void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) { @@ -62,217 +64,261 @@ void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pd } +void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, fapi_nr_dl_config_request_t *dl_config, int rnti_type, int ss_id, uint8_t dci_format){ + + uint16_t monitoringSymbolsWithinSlot; + uint8_t bwp_id = 1, coreset_id = 1; + int sps; + def_dci_pdu_rel15 = calloc(1,sizeof(dci_pdu_rel15_t)); + AssertFatal(mac->scc != NULL, "scc is null\n"); + NR_ServingCellConfigCommon_t *scc = mac->scc; + NR_BWP_DownlinkCommon_t *bwp_Common = mac->DLbwp[bwp_id - 1]->bwp_Common; + NR_BWP_DownlinkCommon_t *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP; + NR_SearchSpace_t *ss = mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id]; + + // DCI format configuration + rel15->dci_format = dci_format; + + // CORESET configuration + NR_ControlResourceSet_t *coreset = mac->coreset[bwp_id - 1][coreset_id - 1]; + rel15->coreset.duration = coreset->duration; + for (int i = 0; i < 6; i++) + rel15->coreset.frequency_domain_resource[i] = coreset->frequencyDomainResources.buf[i]; + rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; + if (rel15->coreset.CceRegMappingType == FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED) { + struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved; + rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize); + rel15->coreset.InterleaverSize = (interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2 + interleaved->interleaverSize); + AssertFatal(scc->physCellId != NULL, "mac->scc->physCellId is null\n"); + rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : *scc->physCellId; + } else { + rel15->coreset.RegBundleSize = 0; + rel15->coreset.InterleaverSize = 0; + rel15->coreset.ShiftIndex = 0; + } + rel15->coreset.CoreSetType = 1; + rel15->coreset.precoder_granularity = coreset->precoderGranularity; + + // Scrambling RNTI + if (coreset->pdcch_DMRS_ScramblingID) { + rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID; + rel15->coreset.scrambling_rnti = mac->t_crnti; + } else { + rel15->coreset.pdcch_dmrs_scrambling_id = *scc->physCellId; + rel15->coreset.scrambling_rnti = 0; + } + + #ifdef DEBUG_DCI + LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: ss_id %d bwp %p bwp_Id %d controlResourceSetId %d\n", ss_id, mac->DLbwp[bwp_id - 1], mac->DLbwp[bwp_id - 1]->bwp_Id, coreset->controlResourceSetId); + #endif + + // loop over RNTI type and configure resource allocation for DCI + switch(rnti_type) { + case NR_RNTI_C: + // we use DL BWP dedicated + sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; + // for SPS=14 8 MSBs in positions 13 down to 6 + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + rel15->rnti = mac->crnti; + rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, 275); + rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); + rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing; + rel15->dci_length = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format, NR_RNTI_C, rel15->BWPSize, bwp_id); + break; + case NR_RNTI_RA: + // we use the initial DL BWP + sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12; + monitoringSymbolsWithinSlot = (ss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (ss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); + rel15->rnti = mac->ra_rnti; + rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); + rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); //NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); + rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; + rel15->dci_length = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format, NR_RNTI_RA, rel15->BWPSize, bwp_id); + break; + case NR_RNTI_P: + break; + case NR_RNTI_CS: + break; + case NR_RNTI_TC: + break; + case NR_RNTI_SP_CSI: + break; + case NR_RNTI_SI: + break; + case NR_RNTI_SFI: + break; + case NR_RNTI_INT: + break; + case NR_RNTI_TPC_PUSCH: + break; + case NR_RNTI_TPC_PUCCH: + break; + case NR_RNTI_TPC_SRS: + break; + default: + break; + } + for (int i = 0; i < sps; i++) { + if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { + rel15->coreset.StartSymbolIndex = i; + break; + } + } + #ifdef DEBUG_DCI + LOG_D(MAC, "[DCI_CONFIG] Configure DCI PDU: rnti_type %d BWPSize %d BWPStart %d rel15->SubcarrierSpacing %d rel15->dci_format %d rel15->dci_length %d sps %d monitoringSymbolsWithinSlot %d \n", + rnti_type, + rel15->BWPSize, + rel15->BWPStart, + rel15->SubcarrierSpacing, + rel15->dci_format, + rel15->dci_length, + sps, + monitoringSymbolsWithinSlot); + #endif + // add DCI + dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; + dl_config->number_pdus = dl_config->number_pdus + 1; +} + void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, frame_t frame, int slot) { - def_dci_pdu_rel15 = calloc(1,sizeof(dci_pdu_rel15_t)); - - NR_BWP_Downlink_t *bwp; - NR_BWP_DownlinkCommon_t *bwp_Common; - NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated; - NR_SetupRelease_PDCCH_Config_t *pdcch_Config; - NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon; - struct NR_PDCCH_Config__controlResourceSetToAddModList *controlResourceSetToAddModList; - struct NR_PDCCH_Config__searchSpacesToAddModList *searchSpacesToAddModList; - struct NR_UplinkConfig__uplinkBWP_ToAddModList *uplinkBWP_ToAddModList; - NR_SearchSpace_t *NR_SearchSpace; - NR_ControlResourceSet_t *coreset; - - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; + int ss_id; + uint8_t bwp_id = 1, coreset_id = 1; NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; + NR_BWP_Downlink_t *bwp = mac->DLbwp[bwp_id - 1]; - uint8_t bwp_id = 1; - int ss_id, sps; + #ifdef DEBUG_DCI + LOG_D(MAC, "[DCI_CONFIG] ra_rnti %p (%x) crnti %p (%x) t_crnti %p (%x)\n", &mac->ra_rnti, mac->ra_rnti, &mac->crnti, mac->crnti, &mac->t_crnti, mac->t_crnti); + #endif - // get PDCCH configuration(s) (Coreset, SearchSpace, etc...) from BWP Dedicated in serving cell config dedicated (scd) - // get BWP 1, Coreset ID 0, SearchSpace ID 0 (i.e. configured in MIB and in ServingCellConfigCommon) + // loop over all available SS for BWP ID 1, CORESET ID 1 + for (ss_id = 0; ss_id < FAPI_NR_MAX_SS_PER_CORESET && mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id] != NULL; ss_id++){ + NR_SearchSpace_t *ss = mac->SSpace[bwp_id - 1][coreset_id - 1][ss_id]; + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + NR_BWP_DownlinkCommon_t *bwp_Common = bwp->bwp_Common; + NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; + struct NR_PhysicalCellGroupConfig *phy_cgc = mac->scg->physicalCellGroupConfig; + switch (ss->searchSpaceType->present){ + case NR_SearchSpace__searchSpaceType_PR_common: + // this is for CSSs, we use BWP common and pdcch_ConfigCommon - // Check dedicated DL BWP - if (mac->DLbwp[0] == NULL) { - NR_SearchSpace_t *ss; - int ss_id = 0; - - AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n"); - AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count); - mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]; - - dl_bwp_Dedicated = mac->DLbwp[0]->bwp_Dedicated; - AssertFatal(dl_bwp_Dedicated != NULL, "dl_bwp_Dedicated is null\n"); - - bwp_Common = mac->DLbwp[0]->bwp_Common; - AssertFatal(bwp_Common != NULL, "bwp_Common is null\n"); - - pdcch_Config = dl_bwp_Dedicated->pdcch_Config; - AssertFatal(pdcch_Config != NULL, "pdcch_Config is null\n"); - - pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; - AssertFatal(pdcch_ConfigCommon != NULL, "pdcch_ConfigCommon is null\n"); - AssertFatal(pdcch_ConfigCommon->choice.setup->ra_SearchSpace != NULL, "ra_SearchSpace must be available in DL BWP\n"); - - controlResourceSetToAddModList = pdcch_Config->choice.setup->controlResourceSetToAddModList; - AssertFatal(controlResourceSetToAddModList != NULL, "controlResourceSetToAddModList is null\n"); - - AssertFatal(controlResourceSetToAddModList->list.count == 1, "controlResourceSetToAddModList->list.count=%d\n", controlResourceSetToAddModList->list.count); - - mac->coreset[0][0] = controlResourceSetToAddModList->list.array[0]; - coreset = mac->coreset[0][0]; - AssertFatal(coreset != NULL, "coreset[0][0] is null\n"); - - searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList; - AssertFatal(searchSpacesToAddModList != NULL, "searchSpacesToAddModList is null\n"); - AssertFatal(searchSpacesToAddModList->list.count > 0, "searchSpacesToAddModList is empty\n"); - AssertFatal(searchSpacesToAddModList->list.count < FAPI_NR_MAX_SS_PER_CORESET, "too many searchpaces per coreset %d\n", searchSpacesToAddModList->list.count); - - for (int i = 0; i < searchSpacesToAddModList->list.count; i++) { - ss = searchSpacesToAddModList->list.array[i]; - AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n"); - AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n"); - AssertFatal(*ss->controlResourceSetId == coreset->controlResourceSetId, "ss->controlResourceSetId is unknown\n"); - mac->SSpace[0][0][ss_id] = ss; - ss_id++; - } - } - - // Check dedicated UL BWP - if (mac->ULbwp[0] == NULL) { - uplinkBWP_ToAddModList = scd->uplinkConfig->uplinkBWP_ToAddModList; - AssertFatal(uplinkBWP_ToAddModList != NULL, "uplinkBWP_ToAddModList is null\n"); - AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count); - mac->ULbwp[0] = uplinkBWP_ToAddModList->list.array[bwp_id - 1]; - AssertFatal(mac->ULbwp[0]->bwp_Dedicated != NULL, "UL bwp_Dedicated is null\n"); - } - - bwp = mac->DLbwp[0]; - bwp_Common = bwp->bwp_Common; - pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon; - dl_bwp_Dedicated = bwp->bwp_Dedicated; - pdcch_Config = dl_bwp_Dedicated->pdcch_Config; - searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList; - - // check USSs - ss_id = 0; - NR_SearchSpace = mac->SSpace[0][0][ss_id]; - while(NR_SearchSpace != NULL && ss_id < searchSpacesToAddModList->list.count) { - AssertFatal(NR_SearchSpace->monitoringSymbolsWithinSlot != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot is null\n"); - AssertFatal(NR_SearchSpace->monitoringSymbolsWithinSlot->buf != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot->buf is null\n"); - ss_id++; - } - - if (mac->crnti > 0) { - - NR_SearchSpace_t *css; - NR_SearchSpace_t *uss = NULL; - NR_ServingCellConfigCommon_t *scc; - NR_SearchSpaceId_t ra_SearchSpaceId; - rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; - uint16_t monitoringSymbolsWithinSlot; - uint8_t add_dci = 1; - - AssertFatal(mac->scc != NULL, "scc is null\n"); - - scc = mac->scc; - rel15->dci_format = NR_DL_DCI_FORMAT_1_1; - - // CoReSet configuration - coreset = mac->coreset[0][0]; - rel15->coreset.duration = coreset->duration; - for (int i = 0; i < 6; i++) - rel15->coreset.frequency_domain_resource[i] = coreset->frequencyDomainResources.buf[i]; - - rel15->coreset.CceRegMappingType = coreset->cce_REG_MappingType.present == NR_ControlResourceSet__cce_REG_MappingType_PR_interleaved ? FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED : FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED; - - if (rel15->coreset.CceRegMappingType == FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED) { - struct NR_ControlResourceSet__cce_REG_MappingType__interleaved *interleaved = coreset->cce_REG_MappingType.choice.interleaved; - rel15->coreset.RegBundleSize = (interleaved->reg_BundleSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__reg_BundleSize_n6) ? 6 : (2 + interleaved->reg_BundleSize); - rel15->coreset.InterleaverSize = (interleaved->interleaverSize == NR_ControlResourceSet__cce_REG_MappingType__interleaved__interleaverSize_n6) ? 6 : (2 + interleaved->interleaverSize); - AssertFatal(scc->physCellId != NULL, "mac->scc->physCellId is null\n"); - rel15->coreset.ShiftIndex = interleaved->shiftIndex != NULL ? *interleaved->shiftIndex : *scc->physCellId; - } else { - rel15->coreset.RegBundleSize = 0; - rel15->coreset.InterleaverSize = 0; - rel15->coreset.ShiftIndex = 0; - } - - rel15->coreset.CoreSetType = 1; - rel15->coreset.precoder_granularity = coreset->precoderGranularity; - - if (mac->ra_state == WAIT_RAR){ - - NR_BWP_DownlinkCommon_t *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP; - struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; - AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH CSS list has 0 elements\n"); - - ra_SearchSpaceId = *pdcch_ConfigCommon->choice.setup->ra_SearchSpace; - - // fetch the CSS for RA from the CSS list - for (int i = 0; i < commonSearchSpaceList->list.count; i++) { - css = commonSearchSpaceList->list.array[i]; - if(css->searchSpaceId == ra_SearchSpaceId) - break; - } - - // check CSSs - if(css != NULL) { - AssertFatal(css->monitoringSymbolsWithinSlot != NULL, "css->monitoringSymbolsWithinSlot is null\n"); - AssertFatal(css->monitoringSymbolsWithinSlot->buf != NULL, "css->monitoringSymbolsWithinSlot->buf is null\n"); - } - - if (frame == mac->msg2_rx_frame && slot == mac->msg2_rx_slot){ - sps = initialDownlinkBWP->genericParameters.cyclicPrefix == NULL ? 14 : 12; - monitoringSymbolsWithinSlot = (css->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (css->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - rel15->rnti = mac->ra_rnti; - rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); - rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); // NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); - rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; - rel15->dci_length = nr_dci_size(scc,mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); - for (int i = 0; i < sps; i++) - if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { - rel15->coreset.StartSymbolIndex = i; - break; - } - fill_dci_search_candidates(css, rel15); - } else { - add_dci = 0; + // Fetch configuration for searchSpaceZero + // note: The search space with the SearchSpaceId = 0 identifies the search space configured via PBCH (MIB) and in ServingCellConfigCommon (searchSpaceZero). + if (pdcch_ConfigCommon->choice.setup->searchSpaceZero){ + LOG_D(MAC, "[DCI_CONFIG] Configure SearchSpace#0 of the initial BWP\n"); + LOG_W(MAC, "[DCI_CONFIG] This should not be available yet..."); } - } else if (mac->ra_state == WAIT_CONTENTION_RESOLUTION){ - - rel15->rnti = mac->t_crnti; - - } else { - - rel15->rnti = mac->crnti; - rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, 275); - rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); - rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing; - rel15->dci_length = nr_dci_size(scc,mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); - // get UE-specific search space - for (ss_id = 0; ss_id < FAPI_NR_MAX_SS_PER_CORESET && mac->SSpace[0][0][ss_id] != NULL; ss_id++){ - uss = mac->SSpace[0][0][ss_id]; - if (uss->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_ue_Specific) break; - } - AssertFatal(ss_id < FAPI_NR_MAX_SS_PER_CORESET, "couldn't find a UE-specific SS\n"); - sps = bwp_Common->genericParameters.cyclicPrefix == NULL ? 14 : 12; - // for SPS=14 8 MSBs in positions 13 down to 6 - monitoringSymbolsWithinSlot = (uss->monitoringSymbolsWithinSlot->buf[0]<<(sps-8)) | (uss->monitoringSymbolsWithinSlot->buf[1]>>(16-sps)); - for (int i = 0; i < sps; i++) - if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { - rel15->coreset.StartSymbolIndex = i; - break; + if (ss->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0){ + // check available SS IDs + if (pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->ra_SearchSpace){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type1-PDCCH common random access search space\n"); + switch(mac->ra_state){ + case WAIT_RAR: + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_RA, ss_id, NR_DL_DCI_FORMAT_1_0); + fill_dci_search_candidates(ss, rel15); + break; + case WAIT_CONTENTION_RESOLUTION: + rel15->rnti = mac->t_crnti; + break; + default: + break; + } + } } - fill_dci_search_candidates(uss, rel15); - } + if (pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceSIB1){ + // Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG + LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); + } + } + if (pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation){ + // Configure monitoring of PDCCH candidates in Type0-PDCCH common search space on the MCG + LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); + } + } + if (pdcch_ConfigCommon->choice.setup->pagingSearchSpace){ + if (ss->searchSpaceId == *pdcch_ConfigCommon->choice.setup->pagingSearchSpace){ + // Configure monitoring of PDCCH candidates in Type2-PDCCH common search space on the MCG + LOG_W(MAC, "[DCI_CONFIG] This seach space should not be configured yet..."); + } + } + if (phy_cgc){ + if (phy_cgc->cs_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + if (phy_cgc->ext1){ + if (phy_cgc->ext1->mcs_C_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + } + } + } // end DCI 00 and 01 + // DCI 2_0 + if (ss->searchSpaceType->choice.common->dci_Format2_0){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_0 with CRC scrambled by SFI-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); + } + // DCI 2_1 + if (ss->searchSpaceType->choice.common->dci_Format2_1){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_1 with CRC scrambled by INT-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); + } + // DCI 2_2 + if (ss->searchSpaceType->choice.common->dci_Format2_2){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_2 with CRC scrambled by TPC-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); + } + // DCI 2_3 + if (ss->searchSpaceType->choice.common->dci_Format2_3){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in Type3-PDCCH common search space for DCI format 2_3 with CRC scrambled by TPC-SRS-RNTI \n"); + LOG_W(MAC, "[DCI_CONFIG] This format should not be configured yet..."); + } - // Scrambling RNTI - if (coreset->pdcch_DMRS_ScramblingID) { - rel15->coreset.pdcch_dmrs_scrambling_id = *coreset->pdcch_DMRS_ScramblingID; - rel15->coreset.scrambling_rnti = mac->t_crnti; - } else { - rel15->coreset.pdcch_dmrs_scrambling_id = *scc->physCellId; - rel15->coreset.scrambling_rnti = 0; - } + break; + case NR_SearchSpace__searchSpaceType_PR_ue_Specific: + // this is an USS + if (ss->searchSpaceType->choice.ue_Specific){ + if(ss->searchSpaceType->choice.ue_Specific->dci_Formats == NR_SearchSpace__searchSpaceType__ue_Specific__dci_Formats_formats0_1_And_1_1){ + // Monitors DCI 01 and 11 scrambled with C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI + if (get_softmodem_params()->phy_test == 1 && mac->crnti > 0) { + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in the user specific search space\n"); + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_C, ss_id, NR_DL_DCI_FORMAT_1_1); + fill_dci_search_candidates(ss, rel15); - if (add_dci){ - dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; - dl_config->number_pdus = dl_config->number_pdus + 1; + #ifdef DEBUG_DCI + LOG_D(MAC, "[DCI_CONFIG] ss %d ue_Specific %p searchSpaceType->present %d dci_Formats %d\n", + ss_id, + ss->searchSpaceType->choice.ue_Specific, + ss->searchSpaceType->present, + ss->searchSpaceType->choice.ue_Specific->dci_Formats); + #endif + } + if (phy_cgc){ + if (phy_cgc->cs_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by CS-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + if (phy_cgc->sp_CSI_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by SP-CSI-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + if (phy_cgc->ext1){ + if (phy_cgc->ext1->mcs_C_RNTI){ + LOG_D(MAC, "[DCI_CONFIG] Configure monitoring of PDCCH candidates in user specific search space for dci_Format0_0_AndFormat1_0 with CRC scrambled by MCS-C-RNTI...\n"); + LOG_W(MAC, "[DCI_CONFIG] This RNTI should not be configured yet..."); + } + } + } + } + } + break; + default: + AssertFatal(1 == 0, "[DCI_CONFIG] Unrecognized search space type..."); + break; } } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index cd6e6bf6db..60f331a086 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -757,193 +757,183 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in } */ } - } else if (ul_info && ul_info->slot_tx == 8) { - module_id_t mod_id = ul_info->module_id; - uint32_t gNB_index = ul_info->gNB_index; - int cc_id = ul_info->cc_id; - frame_t rx_frame = ul_info->frame_rx; - slot_t rx_slot = ul_info->slot_rx; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + } else if (ul_info) { - // program PUSCH. this should actually be done upon reception of an UL DCI - nr_dcireq_t dcireq; - nr_scheduled_response_t scheduled_response; + if (get_softmodem_params()->phy_test && ul_info->slot_tx == 8) { // ULSCH is handled only in phy-test mode (consistently with OAI gNB) - //--------------------------Temporary configuration-----------------------------// - uint16_t rnti = 0x1234; - uint32_t rb_size = 50; - uint32_t rb_start = 0; - uint8_t nr_of_symbols = 11; - uint8_t start_symbol_index = 0; - uint8_t nrOfLayers = 1; - uint8_t mcs_index = 9; - uint8_t mcs_table = 0; - uint8_t harq_process_id = 0; - uint8_t rv_index = 0; - uint16_t l_prime_mask = get_l_prime(nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); - uint8_t dmrs_config_type = 0; - uint8_t ptrs_mcs1 = 2; - uint8_t ptrs_mcs2 = 4; - uint8_t ptrs_mcs3 = 10; - uint16_t n_rb0 = 25; - uint16_t n_rb1 = 75; - uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, mcs_index, mcs_table); - uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, rb_size); - //------------------------------------------------------------------------------// + uint8_t nb_dmrs_re_per_rb; + uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; + uint8_t data_existing = 0; + uint16_t TBS_bytes; + uint32_t TBS; + int i; - dcireq.module_id = mod_id; - dcireq.gNB_index = gNB_index; - dcireq.cc_id = cc_id; - dcireq.frame = rx_frame; - dcireq.slot = rx_slot; + module_id_t mod_id = ul_info->module_id; + uint32_t gNB_index = ul_info->gNB_index; + int cc_id = ul_info->cc_id; + frame_t rx_frame = ul_info->frame_rx; + slot_t rx_slot = ul_info->slot_rx; + frame_t frame_tx = ul_info->frame_tx; + slot_t slot_tx = ul_info->slot_tx; + NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + uint8_t access_mode = SCHEDULED_ACCESS; - scheduled_response.dl_config = NULL; - scheduled_response.ul_config = &dcireq.ul_config_req; - scheduled_response.tx_request = NULL; - scheduled_response.module_id = mod_id; - scheduled_response.CC_id = cc_id; - scheduled_response.frame = rx_frame; - scheduled_response.slot = rx_slot; + // program PUSCH. this should actually be done upon reception of an UL DCI + nr_dcireq_t dcireq; + nr_scheduled_response_t scheduled_response; + fapi_nr_tx_request_t tx_req; + fapi_nr_tx_request_body_t tx_req_body; - scheduled_response.ul_config->slot = ul_info->slot_tx; - scheduled_response.ul_config->number_pdus = 1; - scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rnti = rnti; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_size = rb_size; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_start = rb_start; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nr_of_symbols = nr_of_symbols; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = l_prime_mask << start_symbol_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_index = mcs_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = 0; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nrOfLayers = nrOfLayers; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_process_id; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map = pdu_bit_map; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density; - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ue_ptrs_ports_t)); - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + //--------------------------Temporary configuration-----------------------------// + uint16_t rnti = 0x1234; + uint32_t rb_size = 50; + uint32_t rb_start = 0; + uint8_t nr_of_symbols = 11; + uint8_t start_symbol_index = 0; + uint8_t nrOfLayers = 1; + uint8_t mcs_index = 9; + uint8_t mcs_table = 0; + uint8_t harq_process_id = 0; + uint8_t rv_index = 0; + uint16_t l_prime_mask = get_l_prime(nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); + uint8_t dmrs_config_type = 0; + uint8_t ptrs_mcs1 = 2; + uint8_t ptrs_mcs2 = 4; + uint8_t ptrs_mcs3 = 10; + uint16_t n_rb0 = 25; + uint16_t n_rb1 = 75; + uint16_t pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; + uint8_t ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, mcs_index, mcs_table); + uint8_t ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, rb_size); + uint8_t no_data_in_dmrs = 1; + uint16_t number_dmrs_symbols = 0; + uint16_t ul_dmrs_symb_pos = l_prime_mask << start_symbol_index; + //------------------------------------------------------------------------------// - if (1 << ptrs_time_density >= nr_of_symbols) { - scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + for (i = start_symbol_index; i < start_symbol_index + nr_of_symbols; i++) { + if((ul_dmrs_symb_pos >> i) & 0x01) + number_dmrs_symbols += 1; + } + + if(no_data_in_dmrs) + nb_dmrs_re_per_rb = 12; + else + nb_dmrs_re_per_rb = ((dmrs_config_type == pusch_dmrs_type1) ? 6:4); + + TBS = nr_compute_tbs(nr_get_Qm_ul(mcs_index, 0), + nr_get_code_rate_ul(mcs_index, 0), + rb_size, + nr_of_symbols, + nb_dmrs_re_per_rb*number_dmrs_symbols, + 0, + 0, + nrOfLayers); + TBS_bytes = TBS/8; + + if (IS_SOFTMODEM_NOS1){ + // Getting IP traffic to be transmitted + data_existing = nr_ue_get_sdu(mod_id, + cc_id, + frame_tx, + slot_tx, + 0, + ulsch_input_buffer, + TBS_bytes, + &access_mode); + } + + //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity + if (!IS_SOFTMODEM_NOS1 || !data_existing) { + //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid + //and block this traffic from being forwarded to the upper layers at the gNB + LOG_D(PHY, "Random data to be tranmsitted: \n"); + + //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2) + //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should + //have a valid LCID (nr_process_mac_pdu function) + ulsch_input_buffer[0] = 0x31; + + for (i = 1; i < TBS_bytes; i++) { + ulsch_input_buffer[i] = (unsigned char) rand(); + //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); + } + } + +#ifdef DEBUG_MAC_PDU + + LOG_D(PHY, "Is data existing ?: %d \n", data_existing); + LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", TBS_bytes); + for (i = 0; i < TBS_bytes; i++) { + printf("%02x", ulsch_input_buffer[i]); + } + printf("\n"); + +#endif + + dcireq.module_id = mod_id; + dcireq.gNB_index = gNB_index; + dcireq.cc_id = cc_id; + dcireq.frame = rx_frame; + dcireq.slot = rx_slot; + + scheduled_response.dl_config = NULL; + scheduled_response.ul_config = &dcireq.ul_config_req; + // Config UL TX PDU + tx_req.slot = slot_tx; + tx_req.sfn = frame_tx; + // tx_req->tx_config // TbD + tx_req.number_of_pdus = 1; + tx_req_body.pdu_length = TBS_bytes; + tx_req_body.pdu_index = 0; + tx_req_body.pdu = ulsch_input_buffer; + + scheduled_response.tx_request = &tx_req; + scheduled_response.tx_request->tx_request_body = &tx_req_body; + scheduled_response.module_id = mod_id; + scheduled_response.CC_id = cc_id; + scheduled_response.frame = rx_frame; + scheduled_response.slot = rx_slot; + + scheduled_response.ul_config->slot = ul_info->slot_tx; + scheduled_response.ul_config->number_pdus = 1; + scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rnti = rnti; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_size = rb_size; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_start = rb_start; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nr_of_symbols = nr_of_symbols; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.start_symbol_index = start_symbol_index; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.ul_dmrs_symb_pos = ul_dmrs_symb_pos; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.dmrs_config_type = dmrs_config_type; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_index = mcs_index; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.mcs_table = mcs_table; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.num_dmrs_cdm_grps_no_data = 1; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.new_data_indicator = 0; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.rv_index = rv_index; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.nrOfLayers = nrOfLayers; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_data.harq_process_id = harq_process_id; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map = pdu_bit_map; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_time_density = ptrs_time_density; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_freq_density = ptrs_freq_density; + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list = (nfapi_nr_ue_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ue_ptrs_ports_t)); + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + + if (1 << ptrs_time_density >= nr_of_symbols) { + scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + } + + if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ + mac->if_module->scheduled_response(&scheduled_response); + } + + // TODO: expand + // Note: Contention resolution is currently not active + if (mac->RA_contention_resolution_timer_active == 1) + ue_contention_resolution(mod_id, gNB_index, cc_id, ul_info->frame_tx); } - - if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){ - mac->if_module->scheduled_response(&scheduled_response); - } - - // TODO: expand - // Note: Contention resolution is currently not active - if (mac->RA_contention_resolution_timer_active == 1) - ue_contention_resolution(mod_id, gNB_index, cc_id, ul_info->frame_tx); } - return UE_CONNECTION_OK; } -// Notes: -// - Type1-PDCCH CSS configuration from ra-SearchSpace. -// - Msg2 is scheduled in the mixed slot or in the last dl slot if they are allowed by the Type 1 Common Search Space configuration -// todo: -// - if Type1-PDCCH CSS is not configured in RRC message (Coreset and SearchSpace), UE searches in Type 0 PDCCH CSS. -void nr_ue_msg2_scheduler(module_id_t mod_id, - uint16_t rach_frame, - uint16_t rach_slot, - uint16_t *msg2_frame, - uint16_t *msg2_slot){ - - uint8_t bwp_id = 1; - NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - NR_CellGroupConfig_t *scg = mac->scg; - NR_ServingCellConfigCommon_t *scc = mac->scc; - NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id - 1]; - NR_SearchSpace_t *ss; - struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList; - uint8_t mu = *scc->ssbSubcarrierSpacing; - uint8_t response_window = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow; - uint8_t slot_window, slot_limit, frame_limit; - uint16_t start_next_period, monitoring_slot_period, monitoring_offset; - - // number of mixed slot or of last dl slot if there is no mixed slot - uint16_t last_dl_slot_period = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; - uint16_t nr_dl_symbols = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols; - uint16_t nr_ul_symbols = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; - - // lenght of tdd period in slots - uint16_t tdd_period_slot = last_dl_slot_period + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - - AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH common SearchSpace list has 0 elements\n"); - - LOG_D(MAC, "Frame %d, Slot %d: Scheduling Msg2 reception \n", rach_frame, rach_slot); - - // Common searchspace list - for (int i = 0; i < commonSearchSpaceList->list.count; i++) { - ss = commonSearchSpaceList->list.array[i]; - if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace) - // retrieving ra pdcch monitoring period and offset - find_monitoring_periodicity_offset_common(ss, &monitoring_slot_period, &monitoring_offset); - } - - if (nr_dl_symbols == 0) - last_dl_slot_period--; - if ((nr_dl_symbols > 0) || (nr_ul_symbols > 0)) - tdd_period_slot++; - - // computing start of next period - start_next_period = (rach_slot - (rach_slot % tdd_period_slot) + tdd_period_slot) % nr_slots_per_frame[mu]; - *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot - *msg2_frame = (*msg2_slot > rach_slot) ? rach_frame : (rach_frame +1); - - switch(response_window){ - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: - slot_window = 1; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: - slot_window = 2; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: - slot_window = 4; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: - slot_window = 8; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: - slot_window = 10; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: - slot_window = 20; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: - slot_window = 40; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: - slot_window = 80; - break; - default: - AssertFatal(1==0,"Invalid response window value %d\n",response_window); - } - AssertFatal(slot_window<=nr_slots_per_frame[mu], "Msg2 response window needs to be lower or equal to 10ms"); - - // slot and frame limit to transmit msg2 according to response window - slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu]; - frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1); - - // go to previous slot if the current scheduled slot is beyond the response window - // and if the slot is not among the PDCCH monitored ones (38.213 10.1) - while ((*msg2_slot > slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu] + *msg2_slot - monitoring_offset) % monitoring_slot_period != 0)) { - if((*msg2_slot % tdd_period_slot) > 0) - (*msg2_slot)--; - else - AssertFatal(1 == 0, "No available DL slot to schedule reception of msg2 has been found"); - } - LOG_D(MAC, "Scheduled Msg2 reception in Frame %d, Slot %d: \n", *msg2_frame, *msg2_slot); -} - // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x // It fills the PRACH PDU per each FD occasion. // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. @@ -969,6 +959,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s config_index = rach_ConfigGeneric->prach_ConfigurationIndex; mac->RA_offset = 2; // to compensate the rx frame offset at the gNB + mac->generate_nr_prach = 0; // Reset flag for PRACH generation if (is_nr_UL_slot(scc, slotP)) { @@ -1090,8 +1081,8 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s } } } - } else { - mac->generate_nr_prach = 0; + } else if (mac->ra_state == RA_SUCCEEDED){ + mac->generate_nr_prach = 2; } mac->scheduled_response.ul_config = ul_config; } @@ -2235,9 +2226,14 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; if (pdsch_TimeDomainAllocationList) { - AssertFatal(pdsch_TimeDomainAllocationList->list.count > time_domain_ind, - "time_domain_ind %d >= pdsch->TimeDomainAllocationList->list.count %d\n", - time_domain_ind,pdsch_TimeDomainAllocationList->list.count); + if (time_domain_ind >= pdsch_TimeDomainAllocationList->list.count) { + LOG_E(MAC, "time_domain_ind %d >= pdsch->TimeDomainAllocationList->list.count %d\n", + time_domain_ind, pdsch_TimeDomainAllocationList->list.count); + dlsch_config_pdu->start_symbol = 0; + dlsch_config_pdu->number_symbols = 0; + return -1; + } + int startSymbolAndLength = pdsch_TimeDomainAllocationList->list.array[time_domain_ind]->startSymbolAndLength; int S,L; SLIV2SL(startSymbolAndLength,&S,&L); @@ -2315,7 +2311,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc AssertFatal(mac->DLbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); AssertFatal(mac->ULbwp[0]!=NULL,"DLbwp[0] should not be zero here!\n"); - const uint16_t n_RB_DLBWP = NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); + const uint16_t n_RB_DLBWP = (mac->ra_state == WAIT_RAR) ? NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275) : NRRIV2BW(mac->DLbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); const uint16_t n_RB_ULBWP = NRRIV2BW(mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275); LOG_D(MAC,"nr_ue_process_dci at MAC layer with dci_format=%d (DL BWP %d, UL BWP %d)\n",dci_format,n_RB_DLBWP,n_RB_ULBWP); @@ -2345,10 +2341,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val); /* TIME_DOM_RESOURCE_ASSIGNMENT */ - nr_ue_process_dci_time_dom_resource_assignment(mac, - pusch_config_pdu_0_0,NULL, - dci->time_domain_assignment.val); - + if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_0,NULL,dci->time_domain_assignment.val) < 0) + break; /* FREQ_HOPPING_FLAG */ if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) @@ -2421,8 +2415,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val); /* TIME_DOM_RESOURCE_ASSIGNMENT */ - nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL, - dci->time_domain_assignment.val); + if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL,dci->time_domain_assignment.val) < 0) + break; /* FREQ_HOPPING_FLAG */ if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) @@ -2752,14 +2746,18 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,n_RB_DLBWP,dci->frequency_domain_assignment.val); /* TIME_DOM_RESOURCE_ASSIGNMENT */ - nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0, - dci->time_domain_assignment.val); - + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val) < 0) + break; /* dmrs symbol positions*/ dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, mac->scc->dmrs_TypeA_Position, dlsch_config_pdu_1_0->number_symbols); - dlsch_config_pdu_1_0->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 1 : 2; + dlsch_config_pdu_1_0->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; + /* number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214 version 15.9.0 Release 15 */ + if (dlsch_config_pdu_1_0->number_symbols == 2) + dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 1; + else + dlsch_config_pdu_1_0->n_dmrs_cdm_groups = 2; /* VRB_TO_PRB_MAPPING */ dlsch_config_pdu_1_0->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; /* MCS */ @@ -2820,10 +2818,11 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc dlsch_config_pdu_1_0->pucch_resource_id, dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind); - if (mac->ra_rnti == rnti) + if (mac->RA_window_cnt >= 0 && rnti == mac->ra_rnti){ dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; - else + } else { dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; + } // dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.N_RB_BWP = n_RB_DLBWP; @@ -2872,13 +2871,16 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val); /* TIME_DOM_RESOURCE_ASSIGNMENT */ - nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1, - dci->time_domain_assignment.val); + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val) < 0) + break; /* dmrs symbol positions*/ dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, mac->scc->dmrs_TypeA_Position, dlsch_config_pdu_1_1->number_symbols); - dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 1 : 2; + dlsch_config_pdu_1_1->dmrsConfigType = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1; + /* TODO: fix number of DM-RS CDM groups without data according to subclause 5.1.6.2 of 3GPP TS 38.214, + using tables 7.3.1.2.2-1, 7.3.1.2.2-2, 7.3.1.2.2-3, 7.3.1.2.2-4 of 3GPP TS 38.212 */ + dlsch_config_pdu_1_1->n_dmrs_cdm_groups = 1; /* VRB_TO_PRB_MAPPING */ if (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.resource_allocation != 0) dlsch_config_pdu_1_1->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; @@ -3131,6 +3133,7 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, case NR_DL_DCI_FORMAT_1_0: switch(rnti_type) { case NR_RNTI_RA: + N_RB = NRRIV2BW(mac->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); // TBR hotfix // Freq domain assignment fsize = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); pos=fsize; @@ -3142,7 +3145,7 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, pos+=4; dci_pdu_rel15->time_domain_assignment.val = (*dci_pdu >> (dci_size-pos))&0xf; #ifdef DEBUG_EXTRACT_DCI - LOG_D(MAC,"time-domain assignment %d (3 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu); + LOG_D(MAC,"time-domain assignment %d (4 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_domain_assignment.val,dci_size-pos,*dci_pdu); #endif // VRB to PRB mapping @@ -3165,8 +3168,6 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, #endif break; - mac->rnti_type = rnti_type; - case NR_RNTI_C: // indicating a DL DCI format 1bit diff --git a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c index 31a865f317..8d52db6747 100644 --- a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c +++ b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c @@ -107,9 +107,10 @@ uint16_t nr_ue_process_rar(module_id_t mod_id, uint8_t n_subPDUs = 0; // number of RAR payloads uint8_t n_subheaders = 0; // number of MAC RAR subheaders //uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs - unsigned char freq_hopping, msg3_t_alloc, mcs, tpc_command, csi_req; - uint16_t ta_command = 0, msg3_f_alloc, bwp_size; - int f_alloc, mask; + //unsigned char freq_hopping, msg3_t_alloc, mcs, tpc_command, csi_req; // WIP + //uint16_t ta_command = 0, msg3_f_alloc, bwp_size; // WIP + uint16_t ta_command = 0; + //int f_alloc, mask; // WIP AssertFatal(CC_id == 0, "RAR reception on secondary CCs is not supported yet\n"); @@ -143,6 +144,7 @@ uint16_t nr_ue_process_rar(module_id_t mod_id, // LOG_I(MAC, "[UE %d][RAPROC] Frame %d Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", // mod_id, frameP, *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index); + #if 0 // TbD WIP Msg3 development ongoing if (ue_mac->RA_RAPID_found) { // TC-RNTI *t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); @@ -200,6 +202,7 @@ uint16_t nr_ue_process_rar(module_id_t mod_id, ue_mac->t_crnti = 0; ta_command = (0xffff); } + #endif // move the selected RAR to the front of the RA_PDSCH buffer memcpy((void *) (selected_rar_buffer + 0), (void *) rarh, 1); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 01c18ed997..705e1e2815 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -42,8 +42,7 @@ #include "SIMULATION/TOOLS/sim.h" // for taus extern RAN_CONTEXT_t RC; - -const uint8_t nr_slots_per_frame_mac[5] = {10, 20, 40, 80, 160}; +extern const uint8_t nr_slots_per_frame[5]; uint8_t DELTA[4]= {2,3,4,6}; @@ -187,7 +186,7 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, tdd_period_slot++; // computing start of next period - uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame_mac[mu]; + uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu]; *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot *msg2_frame = (*msg2_slot>(rach_slot))? rach_frame : (rach_frame +1); @@ -219,16 +218,16 @@ void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, default: AssertFatal(1==0,"Invalid response window value %d\n",response_window); } - AssertFatal(slot_window<=nr_slots_per_frame_mac[mu],"Msg2 response window needs to be lower or equal to 10ms"); + AssertFatal(slot_window<=nr_slots_per_frame[mu],"Msg2 response window needs to be lower or equal to 10ms"); // slot and frame limit to transmit msg2 according to response window - uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame_mac[mu]; + uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu]; //uint8_t frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1); // go to previous slot if the current scheduled slot is beyond the response window // and if the slot is not among the PDCCH monitored ones (38.213 10.1) - while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame_mac[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) { + while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0)) { if((*msg2_slot%tdd_period_slot) > 0) (*msg2_slot)--; else @@ -399,11 +398,11 @@ void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc, uint8_t k2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2; temp_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213 - ra->Msg3_slot = temp_slot%nr_slots_per_frame_mac[mu]; - if (nr_slots_per_frame_mac[mu]>temp_slot) + ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu]; + if (nr_slots_per_frame[mu]>temp_slot) ra->Msg3_frame = current_frame; else - ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame_mac[mu]); + ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame[mu]); ra->msg3_nb_rb = 18; ra->msg3_first_rb = 0; @@ -603,7 +602,11 @@ void nr_generate_Msg2(module_id_t module_idP, LOG_D(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw); - mcsIndex = 0; // Qm>2 not allowed for RAR + // Qm>2 not allowed for RAR + if (get_softmodem_params()->do_ra) + mcsIndex = 9; + else + mcsIndex = 0; pdsch_pdu_rel15->pduBitmap = 0; pdsch_pdu_rel15->rnti = RA_rnti; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index da198f7a21..9cc7b26803 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -997,10 +997,9 @@ void schedule_fapi_ul_pdu(int Mod_idP, pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - pusch_pdu->pdu_bit_map &= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + pusch_pdu->pdu_bit_map |= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS } else{ - // if(1<pusch_ptrs.ptrs_time_density >= pusch_pdu->nr_of_symbols) pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 8e71ef087e..d899669035 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -68,8 +68,6 @@ extern RAN_CONTEXT_t RC; -extern int n_active_slices; - // Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs /// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config) uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_15[15] = {2,2,2,3,3,3,1,1,2,2,3,3,1,2,3}; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index 6c23332687..6c6bd30070 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c @@ -114,7 +114,9 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) { int ret=0; while ((sdu_p = pollNotifiedFIFO(&pdcp_sdu_list)) != NULL ) { pdcp_data_ind_header_t * pdcpHead=(pdcp_data_ind_header_t *)NotifiedFifoData(sdu_p); - AssertFatal(pdcpHead->inst==ctxt_pP->module_id, "To implement correctly multi module id\n"); + + /* Note: we ignore the instance ID in the context and use the one in the + * PDCP packet to pick the right socket below */ int rb_id = pdcpHead->rb_id; int sizeToWrite= sizeof (pdcp_data_ind_header_t) + @@ -130,19 +132,19 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) { sizeof(sidelink_pc5s_element), 0, (struct sockaddr *)&prose_pdcp_addr,sizeof(prose_pdcp_addr) ); } else if (UE_NAS_USE_TUN) { - //ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite ); + //ret = write(nas_sock_fd[pdcpHead->inst], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite ); if(rb_id == mbms_rab_id){ ret = write(nas_sock_mbms_fd, pdcpData,sizeToWrite ); LOG_I(PDCP,"[PDCP_FIFOS] ret %d TRIED TO PUSH MBMS DATA TO rb_id %d handle %d sizeToWrite %d\n", - ret,rb_id,nas_sock_fd[ctxt_pP->module_id],sizeToWrite); + ret,rb_id,nas_sock_fd[pdcpHead->inst],sizeToWrite); } else { if( LOG_DEBUGFLAG(DEBUG_PDCP) ) log_dump(PDCP, pdcpData, sizeToWrite, LOG_DUMP_CHAR,"PDCP output to be sent to TUN interface: \n"); - ret = write(nas_sock_fd[ctxt_pP->module_id], pdcpData,sizeToWrite ); + ret = write(nas_sock_fd[pdcpHead->inst], pdcpData,sizeToWrite ); LOG_T(PDCP,"[UE PDCP_FIFOS] ret %d TRIED TO PUSH DATA TO rb_id %d handle %d sizeToWrite %d\n", - ret,rb_id,nas_sock_fd[ctxt_pP->module_id],sizeToWrite); + ret,rb_id,nas_sock_fd[pdcpHead->inst],sizeToWrite); } } else if (ENB_NAS_USE_TUN) { if( LOG_DEBUGFLAG(DEBUG_PDCP) ) diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index b18831b546..e63f93b028 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -117,13 +117,6 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ if (is_nr_UL_slot(mac->scc, ul_info->slot_tx) && get_softmodem_params()->do_ra){ nr_ue_prach_scheduler(module_id, ul_info->frame_tx, ul_info->slot_tx); - if (mac->generate_nr_prach){ - //uint16_t monitoring_slot_period, monitoring_offset; - uint16_t rach_frame = mac->scheduled_response.ul_config->sfn; - uint16_t rx_rach_frame = (rach_frame + mac->RA_offset) % MAX_FRAME_NUMBER; // compensate 2 frames offset delay at gNB side - uint16_t rach_slot = mac->scheduled_response.ul_config->slot; - nr_ue_msg2_scheduler(module_id, rx_rach_frame, rach_slot, &mac->msg2_rx_frame, &mac->msg2_rx_slot); - } } switch(ret){ @@ -154,7 +147,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request; if (!dl_info->dci_ind && !dl_info->rx_ind) { - // UL indication to schedule reception DCI reception + // UL indication to schedule DCI reception nr_ue_scheduler(dl_info, NULL); } else { // UL indication after reception of DCI or DL PDU diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index 7e3763fb4f..c537c536b2 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c @@ -2310,7 +2310,7 @@ uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, LTE_SL_Destin return((enc_rval.encoded+7)/8); } -uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) { +uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, uint8_t sel_plmn_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) { asn_enc_rval_t enc_rval; LTE_UL_DCCH_Message_t ul_dcch_msg; LTE_RRCConnectionSetupComplete_t *rrcConnectionSetupComplete; @@ -2323,7 +2323,7 @@ uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uin rrcConnectionSetupComplete->criticalExtensions.choice.c1.present = LTE_RRCConnectionSetupComplete__criticalExtensions__c1_PR_rrcConnectionSetupComplete_r8; rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension=CALLOC(1, sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension)); - rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 1; + rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= sel_plmn_id; rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME = NULL;//calloc(1,sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME)); /* diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.h b/openair2/RRC/LTE/MESSAGES/asn1_msg.h index dda2340610..640d18a61f 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.h +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.h @@ -142,7 +142,11 @@ uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, LTE_SL_Destina /** \brief Generate an RRCConnectionSetupComplete UL-DCCH-Message (UE) @param buffer Pointer to PER-encoded ASN.1 description of UL-DCCH-Message PDU @returns Size of encoded bit stream in bytes*/ -uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength, +uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, + uint8_t *buffer, + const uint8_t Transaction_id, + uint8_t sel_plmn_id, + const int dedicatedInfoNASLength, const char *dedicatedInfoNAS); /** \brief Generate an RRCConnectionReconfigurationComplete UL-DCCH-Message (UE) diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 4116f5367e..bdf992c76a 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -128,8 +128,13 @@ static int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t * \param ctxt_pP Running context * \param eNB_index Index of corresponding eNB/CH * \param Transaction_id Transaction identifier + * \param sel_plmn_id selected PLMN Identity */ -static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id ); +static void rrc_ue_generate_RRCConnectionSetupComplete( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t eNB_index, + const uint8_t Transaction_id, + uint8_t sel_plmn_id); /** \brief Generates/Encodes RRCConnectionReconfigurationComplete message at UE * \param ctxt_pP Running context @@ -367,6 +372,7 @@ char openair_rrc_ue_init( const module_id_t ue_mod_idP, const unsigned char eNB_ rrc_set_state (ue_mod_idP, RRC_STATE_INACTIVE); rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_INACTIVE); LOG_I(RRC,"[UE %d] INIT State = RRC_IDLE (eNB %d)\n",ctxt.module_id,eNB_index); + UE_rrc_inst[ctxt.module_id].selected_plmn_identity = 1; UE_rrc_inst[ctxt.module_id].Info[eNB_index].State=RRC_IDLE; UE_rrc_inst[ctxt.module_id].Info[eNB_index].T300_active = 0; UE_rrc_inst[ctxt.module_id].Info[eNB_index].T304_active = 0; @@ -490,7 +496,11 @@ rrc_t310_expiration( } //----------------------------------------------------------------------------- -static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id ) { +static void rrc_ue_generate_RRCConnectionSetupComplete( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t eNB_index, + const uint8_t Transaction_id, + uint8_t sel_plmn_id) { uint8_t buffer[100]; uint8_t size; const char *nas_msg; @@ -504,7 +514,7 @@ static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *c nas_msg_length = sizeof(nas_attach_req_imsi); } - size = do_RRCConnectionSetupComplete(ctxt_pP->module_id, buffer, Transaction_id, nas_msg_length, nas_msg); + size = do_RRCConnectionSetupComplete(ctxt_pP->module_id, buffer, Transaction_id, sel_plmn_id, nas_msg_length, nas_msg); LOG_I(RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCConnectionSetupComplete (bytes%d, eNB %d)\n", ctxt_pP->module_id,ctxt_pP->frame, size, eNB_index); LOG_D(RLC, @@ -624,7 +634,8 @@ int rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const SRB_INFO *co rrc_ue_generate_RRCConnectionSetupComplete( ctxt_pP, eNB_index, - dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.rrc_TransactionIdentifier); + dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.rrc_TransactionIdentifier, + UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); rval = 0; break; @@ -2794,44 +2805,43 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, LTE_SystemInformationBlockType1_t *sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN ); LOG_I( RRC, "[UE %d] : Dumping SIB 1\n", ctxt_pP->module_id ); - LTE_PLMN_Identity_t *PLMN_identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->plmn_Identity; - int mccdigits = PLMN_identity->mcc->list.count; - int mncdigits = PLMN_identity->mnc.list.count; - int mcc; + const int n = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; + for (int i = 0; i < n; ++i) { + LTE_PLMN_Identity_t *PLMN_identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[i]->plmn_Identity; + int mccdigits = PLMN_identity->mcc->list.count; + int mncdigits = PLMN_identity->mnc.list.count; - if (mccdigits == 2) { - mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1]; - } else { - mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2]; + int mcc; + if (mccdigits == 2) { + mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1]; + } else { + mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2]; + } + + int mnc; + if (mncdigits == 2) { + mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1]; + } else { + mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2]; + } + + LOG_I( RRC, "PLMN %d MCC %0*d, MNC %0*d\n", i + 1, mccdigits, mcc, mncdigits, mnc); + // search internal table for provider name + int plmn_ind = 0; + + while (plmn_data[plmn_ind].mcc > 0) { + if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) { + LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short ); + break; + } + + plmn_ind++; + } } - - int mnc; - - if (mncdigits == 2) { - mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1]; - } else { - mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2]; - } - - LOG_I( RRC, "PLMN MCC %0*d, MNC %0*d, TAC 0x%04x\n", mccdigits, mcc, mncdigits, mnc, + LOG_I( RRC, "TAC 0x%04x\n", ((sib1->cellAccessRelatedInfo.trackingAreaCode.size == 2)?((sib1->cellAccessRelatedInfo.trackingAreaCode.buf[0]<<8) + sib1->cellAccessRelatedInfo.trackingAreaCode.buf[1]):0)); LOG_I( RRC, "cellReservedForOperatorUse : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse, SIBreserved(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse) ); - // search internal table for provider name - int plmn_ind = 0; - - while (plmn_data[plmn_ind].mcc > 0) { - if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) { - LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short ); - break; - } - - plmn_ind++; - } - - if (plmn_data[plmn_ind].mcc < 0) { - LOG_I( RRC, "Found Unknown operator (no entry in internal table)\n" ); - } LOG_I( RRC, "cellAccessRelatedInfo.cellIdentity : raw:%"PRIu32" decoded:%02x.%02x.%02x.%02x\n", BIT_STRING_to_uint32( &sib1->cellAccessRelatedInfo.cellIdentity ), @@ -2970,6 +2980,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp; itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); cell_valid = 1; + UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity = plmn + 1; break; } } @@ -2980,7 +2991,11 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, MessageDef *msg_p; msg_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_NEXT_CELL_REQ); itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); - LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM, the message PHY_FIND_NEXT_CELL_REQ is sent but lost in current UE implementation! \n"); + LOG_E(RRC, + "Synched with a cell, but PLMN doesn't match our SIM " + "(selected_plmn_identity %d), the message PHY_FIND_NEXT_CELL_REQ " + "is sent but lost in current UE implementation!\n", + UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); } } diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index e366061674..3c02c45bc1 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -809,6 +809,7 @@ typedef struct UE_RRC_INST_s { Rrc_Sub_State_t RrcSubState; plmn_t plmnID; Byte_t rat; + uint8_t selected_plmn_identity; as_nas_info_t initialNasMsg; OAI_UECapability_t *UECap; uint8_t *UECapability; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 1d44751dca..16d5065d37 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -994,11 +994,14 @@ void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag) { pthread_mutex_unlock(&lock_ue_freelist); } +extern int16_t find_dlsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +extern int16_t find_ulsch(uint16_t rnti, PHY_VARS_eNB *eNB,find_type_t type); +extern void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch); +extern void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch); + void release_UE_in_freeList(module_id_t mod_id) { int i, j, CC_id, pdu_number; protocol_ctxt_t ctxt; - LTE_eNB_ULSCH_t *ulsch = NULL; - LTE_eNB_DLSCH_t *dlsch = NULL; nfapi_ul_config_request_body_t *ul_req_tmp = NULL; PHY_VARS_eNB *eNB_PHY = NULL; struct rrc_eNB_ue_context_s *ue_context_pP = NULL; @@ -1032,6 +1035,25 @@ void release_UE_in_freeList(module_id_t mod_id) { for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { eNB_PHY = RC.eNB[mod_id][CC_id]; + int id; + + // clean ULSCH entries for rnti + id = find_ulsch(rnti,eNB_PHY,SEARCH_EXIST); + if (id>=0) clean_eNb_ulsch(eNB_PHY->ulsch[id]); + + // clean DLSCH entries for rnti + id = find_dlsch(rnti,eNB_PHY,SEARCH_EXIST); + if (id>=0) clean_eNb_dlsch(eNB_PHY->dlsch[id][0]); + + // clean UCI entries for rnti + for (i=0; iuci_vars[i].rnti == rnti) { + LOG_I(MAC, "clean eNb uci_vars[%d] UE %x \n",i, rnti); + memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI)); + } + } + + /* for (i=0; iulsch[i]; @@ -1064,6 +1086,7 @@ void release_UE_in_freeList(module_id_t mod_id) { memset(&eNB_PHY->uci_vars[i],0,sizeof(LTE_eNB_UCI)); } } + */ if (flexran_agent_get_rrc_xface(mod_id)) { flexran_agent_get_rrc_xface(mod_id)->flexran_agent_notify_ue_state_change( diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index 27a442ed05..9f92be366b 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -96,36 +96,34 @@ void extract_imsi(uint8_t *pdu_buf, uint32_t pdu_len, rrc_eNB_ue_context_t *ue_c && pdu_len > NAS_MESSAGE_SECURITY_HEADER_SIZE)) return; + /* Decode plain NAS message */ + EMM_msg *e_msg = &nas_msg.plain.emm; + emm_msg_header_t *emm_header = &e_msg->header; + if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) { /* Decode the message authentication code */ DECODE_U32((char *) pdu_buf+size, header->message_authentication_code, size); /* Decode the sequence number */ DECODE_U8((char *) pdu_buf+size, header->sequence_number, size); - } + /* Decode the security header type and the protocol discriminator */ + DECODE_U8(pdu_buf + size, *(uint8_t *)(emm_header), size); - /* Note: the value of the pointer (i.e. the address) is given by value, so we - * can modify it as we want. The callee retains the original address! */ + /* Check that this is the right message */ + if (emm_header->protocol_discriminator != EPS_MOBILITY_MANAGEMENT_MESSAGE) + return; + } pdu_buf += size; pdu_len -= size; - /* Decode plain NAS message */ - EMM_msg *e_msg = &nas_msg.plain.emm; - emm_msg_header_t *emm_header = &e_msg->header; - /* First decode the EMM message header */ - int e_head_size = 0; /* Check that buffer contains more than only the header */ if (pdu_len <= sizeof(emm_msg_header_t)) return; - /* Decode the security header type and the protocol discriminator */ - DECODE_U8(pdu_buf + e_head_size, *(uint8_t *)(emm_header), e_head_size); + /* First decode the EMM message header */ + int e_head_size = 0; /* Decode the message type */ DECODE_U8(pdu_buf + e_head_size, emm_header->message_type, e_head_size); - /* Check that this is the right message */ - if (emm_header->protocol_discriminator != EPS_MOBILITY_MANAGEMENT_MESSAGE) - return; - pdu_buf += e_head_size; pdu_len -= e_head_size; diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index 6a037b8ee3..bd77272747 100644 --- a/openair2/X2AP/x2ap_eNB.c +++ b/openair2/X2AP/x2ap_eNB.c @@ -116,7 +116,9 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa /* some sanity check - to be refined at some point */ if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { X2AP_ERROR("x2ap_enb_data_p not NULL and sctp state not SCTP_STATE_ESTABLISHED, what to do?\n"); - abort(); + // Allow for a gracious exit when we kill first the gNB, then the eNB + //abort(); + return; } x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams; diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index c228034245..c703501847 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -220,8 +220,21 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * /* Trying to connect to provided list of MME ip address */ for (index = 0; index < s1ap_register_eNB->nb_mme; index++) { + net_ip_address_t *mme_ip = &s1ap_register_eNB->mme_ip_address[index]; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &new_instance->s1ap_mme_head) { + /* Compare whether IPv4 and IPv6 information is already present, in which + * wase we do not register again */ + if (mme->mme_s1_ip.ipv4 == mme_ip->ipv4 && (!mme_ip->ipv4 + || strncmp(mme->mme_s1_ip.ipv4_address, mme_ip->ipv4_address, 16) == 0) + && mme->mme_s1_ip.ipv6 == mme_ip->ipv6 && (!mme_ip->ipv6 + || strncmp(mme->mme_s1_ip.ipv6_address, mme_ip->ipv6_address, 46) == 0)) + break; + } + if (mme) + continue; s1ap_eNB_register_mme(new_instance, - &s1ap_register_eNB->mme_ip_address[index], + mme_ip, &s1ap_register_eNB->enb_ip_address, s1ap_register_eNB->sctp_in_streams, s1ap_register_eNB->sctp_out_streams, diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index c72e7d4130..1d3c280f0e 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -288,7 +288,7 @@ int ethernet_tune(openair0_device *device, /******************* interface level options *************************/ case MTU_SIZE: /* change MTU of the eth interface */ ifr.ifr_addr.sa_family = AF_INET; - strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)-1); ifr.ifr_mtu =value; if (ioctl(eth->sockfdd,SIOCSIFMTU,(caddr_t)&ifr) < 0 ) perror ("[ETHERNET] Can't set the MTU"); @@ -298,7 +298,7 @@ int ethernet_tune(openair0_device *device, case TX_Q_LEN: /* change TX queue length of eth interface */ ifr.ifr_addr.sa_family = AF_INET; - strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name,eth->if_name, sizeof(ifr.ifr_name)-1); ifr.ifr_qlen =value; if (ioctl(eth->sockfdd,SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 ) perror ("[ETHERNET] Can't set the txqueuelen"); diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 1377086e8f..6e94717a6f 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -976,7 +976,6 @@ extern "C" { double usrp_master_clock; if (device_adds[0].get("type") == "b200") { - printf("Found USRP b200\n"); device->type = USRP_B200_DEV; usrp_master_clock = 30.72e6; args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 80b5cd5bac..1ebfb7c77d 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include "common_lib.h" #include @@ -78,11 +79,25 @@ extern RAN_CONTEXT_t RC; #define RFSIMULATOR_PARAMS_DESC {\ {"serveraddr", "\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ {"serverport", "\n", 0, u16ptr:&(rfsimulator->port), defuintval:PORT, TYPE_UINT16, 0 },\ - {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0},\ + {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, strlistptr:NULL, defstrlistval:NULL, TYPE_STRINGLIST,0 },\ {"IQfile", "\n", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\ - {"modelname", "\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 }\ + {"modelname", "\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\ + {"ploss", "\n", 0, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\ + {"forgetfact", "\n", 0, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\ + {"offset", "\n", 0, iptr:&(rfsimulator->chan_offset), defintval:0, TYPE_INT, 0 }\ }; + + +static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); +static telnetshell_cmddef_t rfsimu_cmdarray[] = { + {"setmodel","",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, + {"","",NULL}, +}; + +static telnetshell_vardef_t rfsimu_vardef[] = { + {"",0,NULL} +}; pthread_mutex_t Sockmutex; typedef struct complex16 sample_t; // 2*16 bits complex number @@ -114,6 +129,11 @@ typedef struct { double sample_rate; double tx_bw; int channelmod; + double chan_pathloss; + double chan_forgetfact; + int chan_offset; + void *telnetcmd_qid; + poll_telnetcmdq_func_t poll_telnetcmdq; } rfsimulator_state_t; @@ -148,23 +168,28 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { // Legacy changes directlty the variable channel_model->path_loss_dB place to place // while calling new_channel_desc_scm() with path losses = 0 static bool init_done=false; + if (!init_done) { - uint64_t rand; - FILE *h=fopen("/dev/random","r"); - fread(&rand,sizeof(rand),1,h); - fclose(h); + uint64_t rand; + FILE *h=fopen("/dev/random","r"); + if ( 1 != fread(&rand,sizeof(rand),1,h) ) + LOG_W(HW, "Simulator can't read /dev/random\n"); + fclose(h); randominit(rand); tableNor(rand); init_done=true; } + ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels, bridge->channelmod, bridge->sample_rate, bridge->tx_bw, 30e-9, // TDL delay-spread parameter - 0.0, // forgetting_factor - 0, // maybe used for TA - 0); // path_loss in dB + bridge->chan_forgetfact, // forgetting_factor + bridge->chan_offset, // maybe used for TA + bridge->chan_pathloss); // path_loss in dB + set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID); + random_channel(ptr->channel_model,false); } } @@ -291,6 +316,41 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { rfsimulator->typeStamp = UE_MAGICDL_FDD; } +static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) { + char *modelname=NULL; + int s = sscanf(buff,"%ms\n",&modelname); + if (s == 1) { + int channelmod=modelid_fromname(modelname); + if (channelmod<0) + prnt("ERROR: model %s unknown\n",modelname); + else { + rfsimulator_state_t *t = (rfsimulator_state_t *)arg; + for (int i=0; ibuf[i]; + if (b->conn_sock >= 0 ) { + channel_desc_t *newmodel=new_channel_desc_scm(t->tx_num_channels,t->rx_num_channels, + channelmod, + t->sample_rate, + t->tx_bw, + t->chan_forgetfact, // forgetting_factor + t->chan_offset, // maybe used for TA + t->chan_pathloss); // path_loss in dB + set_channeldesc_owner(newmodel, RFSIMU_MODULEID); + random_channel(newmodel,false); + channel_desc_t *oldmodel=b->channel_model; + b->channel_model=newmodel; + free_channel_desc_scm(oldmodel); + prnt("New model %s applied to channel connected to sock %d\n",modelname,i); + } + } + } + } else { + prnt("ERROR: no model specified\n"); + } + free(modelname); + return CMDSTATUS_FOUND; +} + int server_start(openair0_device *device) { rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; t->typeStamp=ENB_MAGICDL_FDD; @@ -380,6 +440,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp if (t->lastWroteTS > timestamp+nsamps) LOG_E(HW,"Not supported to send Tx out of order (same in USRP) %lu, %lu\n", t->lastWroteTS, timestamp); + t->lastWroteTS=timestamp+nsamps; if (!alreadyLocked) @@ -481,6 +542,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi b->trashingPacket=true; } else if ( b->lastReceivedTS < b->th.timestamp) { int nbAnt= b->th.nbAnt; + if ( b->th.timestamp-b->lastReceivedTS < CirSize ) { for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) { for (int a=0; a < nbAnt; a++) { @@ -491,8 +553,10 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi } else { memset(b->circularBuf, 0, sampleToByte(CirSize,1)); } + if (b->lastReceivedTS != 0 && b->th.timestamp-b->lastReceivedTS > 50 ) LOG_W(HW,"UEsock: %d gap of: %ld in reception\n", fd, b->th.timestamp-b->lastReceivedTS ); + b->lastReceivedTS=b->th.timestamp; } else if ( b->lastReceivedTS > b->th.timestamp && b->th.size == 1 ) { @@ -511,7 +575,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi LOG_E(HW,"UEsock: %d Tx/Rx shift too large Tx:%lu, Rx:%lu\n", fd, t->lastWroteTS, b->lastReceivedTS); pthread_mutex_unlock(&Sockmutex); - b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; + b->transferPtr=(char *)&b->circularBuf[(b->lastReceivedTS*b->th.nbAnt)%CirSize]; b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); } @@ -641,8 +705,10 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo // it seems legacy behavior is: never in UL, each frame in DL if (reGenerateChannel) random_channel(ptr->channel_model,0); + if (t->poll_telnetcmdq) + t->poll_telnetcmdq(t->telnetcmd_qid,t); - for (int a=0; achannel_model != NULL ) // apply a channel model rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a], a, @@ -653,14 +719,16 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ); else { // no channel modeling sample_t *out=(sample_t *)samplesVoid[a]; - const int64_t base=t->nextTimestamp*nbAnt+a; - for ( int i=0; i < nsamps; i++ ) { - const int idx=(i*nbAnt+base)%CirSize; - out[i].r+=ptr->circularBuf[idx].r; - out[i].i+=ptr->circularBuf[idx].i; - } + int nbAnt_tx = ptr->th.nbAnt;//number of Tx antennas + //LOG_I(HW, "nbAnt_tx %d\n",nbAnt_tx); + for (int i=0; i < nsamps; i++) {//loop over nsamps + for (int a_tx=0; a_txcircularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].r; + out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].i; + } // end for a_tx + } // end for i (number of samps) } // end of no channel modeling - } // end for a... + } // end for a (number of rx antennas) } } @@ -735,5 +803,18 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->tx_bw=openair0_cfg->tx_bw; //randominit(0); set_taus_seed(0); + /* look for telnet server, if it is loaded, add the channel modeling commands to it */ + add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); + + if (addcmd != NULL) { + rfsimulator->poll_telnetcmdq = (poll_telnetcmdq_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_POLLCMDQ_FNAME); + addcmd("rfsimu",rfsimu_vardef,rfsimu_cmdarray); + for(int i=0; rfsimu_cmdarray[i].cmdfunc != NULL; i++) { + if ( rfsimu_cmdarray[i].qptr != NULL) { + rfsimulator->telnetcmd_qid = rfsimu_cmdarray[i].qptr; + break; + } + } + } return 0; } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf index 2c37e0d03f..dbcbb2ed4f 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf @@ -248,7 +248,9 @@ RUs = ( max_pdschReferenceSignalPower = -27; max_rxgain = 114; eNB_instances = [0]; - sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + sdr_addrs = "addr=192.168.10.2,mgmt_addr=192.168.10.2,second_addr=192.168.20.2"; clock_src = "external"; } ); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 4715a4e995..82ca4d5428 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -438,9 +438,6 @@ int restart_L1L2(module_id_t enb_id) { } 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)); set_function_spec_param(RC.ru[enb_id]); /* reset the list of connected UEs in the MAC, since in this process with * loose all UEs (have to reconnect) */ @@ -556,6 +553,8 @@ int main ( int argc, char **argv ) MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); init_opt(); + // to make a graceful exit when ctrl-c is pressed + set_softmodem_sighandler(); check_clock(); #ifndef PACKAGE_VERSION # define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" @@ -725,7 +724,7 @@ int main ( int argc, char **argv ) // end of CI modifications //getchar(); if(IS_SOFTMODEM_DOFORMS) - load_softscope("enb"); + load_softscope("enb",NULL); itti_wait_tasks_end(); oai_exit=1; LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit); diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index a45ecd2298..54a9f4a669 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -759,7 +759,7 @@ int main( int argc, char **argv ) { } if(IS_SOFTMODEM_DOFORMS) - load_softscope("ue"); + load_softscope("ue",NULL); config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex);