diff --git a/ci-scripts/Jenkinsfile-gitlab b/ci-scripts/Jenkinsfile-gitlab index 8dfa5c4ec4c93895262d81b6909fe54918d2cac1..c3b997a4e89e015722df42a63979073cae3f3351 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 0000000000000000000000000000000000000000..1249f521728c1e846f7dfb8871185d966292aa40 --- /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=<filename> 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 0000000000000000000000000000000000000000..6954aa392742f1ca77ee64d46e97b468a2614cff --- /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 0000000000000000000000000000000000000000..5b2c90a714d773e456215098095edfd569a428fd --- /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 0000000000000000000000000000000000000000..92af74c300248c020bc8ebedca4b5fc9e62c1f5e --- /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 09d500f203d185fc00fd0778721a1b5e542d4a38..25bbbba091b3ad6b65ed8e5b0a976e883de06a4b 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 8fa99fa61b0be9890c60dd06e46cfa690a7287c8..8f2d38cced95600c4ae587ba65aab2f871d3edc5 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 63358eca38a8f3c79d17db1037daa6702d06c780..d37f205f4e6a11cb72ebacb3455613b52b21d2f9 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 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 +# 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<average>[0-9\.]+ Mbits\/sec) Max Bitrate : (?P<maximum>[0-9\.]+ Mbits\/sec) Min Bitrate : (?P<minimum>[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('<b>' + ueAction + ' Failed</b>\n' + HTML.GethtmlUEFailureMsg()) + HTML.htmlUEFailureMsg='<b>' + ueAction + ' Failed</b>\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('<b>' + ueAction + ' Completed</b>\n' + HTML.GethtmlUEFailureMsg()) + HTML.htmlUEFailureMsg='<b>' + ueAction + ' Completed</b>\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<os_type>[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<kernel_version>[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<uhd_version>[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<uhd_version>[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<nb_cpus>[0-9]+).*Model name: *(?P<model>[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P<cpu_mhz>[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 +# 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() -import sshconnection -import epc -import helpreadme as HELP -import ran -import html -import constants +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) -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) +#----------------------------------------------------------- +# 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() 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 0000000000000000000000000000000000000000..303d5d100660b8d2608a67f58e4950690882ffb8 --- /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 0000000000000000000000000000000000000000..aaf31c1576527dc08985a37dfe1dd2b97eca8d64 --- /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 287c18021e2cf2cabbeafe55a81a6b965e73612e..96f28e21fe3f58e19d56510c3fcac22645a2df05 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<eth_interface>[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 ba0f900f2940482589e3e9711c942031af88cd9a..ed0cf5379a18aa121e0a2cd373a9faf26518366e 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 0000000000000000000000000000000000000000..e80063a120ad9e163a7ef549f296da0f677241fc --- /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 0000000000000000000000000000000000000000..a4caa77075979939cdbe7530caa1f8a399129e57 --- /dev/null +++ b/ci-scripts/xml_files/enb_ocp_usrp210_band7_test_05mhz_tm1.xml @@ -0,0 +1,147 @@ +<!-- + + 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 + +--> +<testCaseList> + <htmlTabRef>test-05-tm1</htmlTabRef> + <htmlTabName>Test-05MHz-TM1</htmlTabName> + <htmlTabIcon>tasks</htmlTabIcon> + <repeatCount>4</repeatCount> + <TestCaseRequestedList> + 030201 + 040101 + 030101 040301 040501 040603 040604 040605 040606 040607 040641 040642 040643 040644 040401 040201 030201 + </TestCaseRequestedList> + <TestCaseExclusionList></TestCaseExclusionList> + + <testCase id="030101"> + <class>Initialize_eNB</class> + <desc>Initialize OCP-eNB (FDD/Band7/5MHz)</desc> + <Initialize_eNB_args>-O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf</Initialize_eNB_args> + <air_interface>ocp</air_interface> + </testCase> + + <testCase id="030201"> + <class>Terminate_eNB</class> + <desc>Terminate OCP-eNB</desc> + <air_interface>ocp</air_interface> + </testCase> + + <testCase id="040101"> + <class>Initialize_UE</class> + <desc>Initialize UE</desc> + </testCase> + + <testCase id="040201"> + <class>Terminate_UE</class> + <desc>Terminate UE</desc> + </testCase> + + <testCase id="040301"> + <class>Attach_UE</class> + <desc>Attach UE</desc> + </testCase> + + <testCase id="040401"> + <class>Detach_UE</class> + <desc>Detach UE</desc> + </testCase> + + <testCase id="040501"> + <class>Ping</class> + <desc>ping (5MHz - 20 sec)</desc> + <ping_args>-c 20</ping_args> + <ping_packetloss_threshold>5</ping_packetloss_threshold> + </testCase> + + <testCase id="040603"> + <class>Iperf</class> + <desc>iperf (5MHz - DL/15Mbps/UDP)(30 sec)(balanced profile)</desc> + <iperf_args>-u -b 15M -t 30 -i 1</iperf_args> + <iperf_packetloss_threshold>50</iperf_packetloss_threshold> + <iperf_profile>balanced</iperf_profile> + </testCase> + + <testCase id="040604"> + <class>Iperf</class> + <desc>iperf (5MHz - DL/15Mbps/UDP)(30 sec)(single-ue profile)</desc> + <iperf_args>-u -b 15M -t 30 -i 1</iperf_args> + <iperf_packetloss_threshold>50</iperf_packetloss_threshold> + <iperf_profile>single-ue</iperf_profile> + </testCase> + + <testCase id="040605"> + <class>Iperf</class> + <desc>iperf (5MHz - DL/15Mbps/UDP)(30 sec)(unbalanced profile)</desc> + <iperf_args>-u -b 15M -t 30 -i 1</iperf_args> + <iperf_packetloss_threshold>50</iperf_packetloss_threshold> + <iperf_profile>unbalanced</iperf_profile> + </testCase> + + <testCase id="040606"> + <class>Iperf</class> + <desc>iperf (5MHz - DL/TCP)(30 sec)(single-ue profile)</desc> + <iperf_args>-t 30 -i 1 -fm</iperf_args> + <iperf_packetloss_threshold>50</iperf_packetloss_threshold> + <iperf_profile>single-ue</iperf_profile> + </testCase> + + <testCase id="040607"> + <class>Iperf</class> + <desc>iperf (5MHz - DL/TCP)(30 sec)(balanced profile)</desc> + <iperf_args>-t 30 -i 1 -fm</iperf_args> + <iperf_packetloss_threshold>50</iperf_packetloss_threshold> + <iperf_profile>balanced</iperf_profile> + </testCase> + + <testCase id="040641"> + <class>Iperf</class> + <desc>iperf (5MHz - UL/9Mbps/UDP)(30 sec)(balanced profile)</desc> + <iperf_args>-u -b 9M -t 30 -i 1 -R</iperf_args> + <iperf_packetloss_threshold>50</iperf_packetloss_threshold> + <iperf_profile>balanced</iperf_profile> + </testCase> + + <testCase id="040642"> + <class>Iperf</class> + <desc>iperf (5MHz - UL/9Mbps/UDP)(30 sec)(single-ue profile)</desc> + <iperf_args>-u -b 9M -t 30 -i 1 -R</iperf_args> + <iperf_packetloss_threshold>50</iperf_packetloss_threshold> + <iperf_profile>single-ue</iperf_profile> + </testCase> + + <testCase id="040643"> + <class>Iperf</class> + <desc>iperf (5MHz - UL/TCP)(30 sec)(single-ue profile)</desc> + <iperf_args>-t 30 -i 1 -fm -R</iperf_args> + <iperf_packetloss_threshold>50</iperf_packetloss_threshold> + <iperf_profile>single-ue</iperf_profile> + </testCase> + + <testCase id="040644"> + <class>Iperf</class> + <desc>iperf (5MHz - UL/TCP)(30 sec)(balanced profile)</desc> + <iperf_args>-t 30 -i 1 -fm -R</iperf_args> + <iperf_packetloss_threshold>50</iperf_packetloss_threshold> + <iperf_profile>balanced</iperf_profile> + </testCase> + +</testCaseList> 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 0000000000000000000000000000000000000000..33a0fc205e0855de99602abc4f7394e89ad98963 --- /dev/null +++ b/ci-scripts/xml_files/enb_ocp_usrp210_build.xml @@ -0,0 +1,38 @@ +<!-- + + 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 + +--> +<testCaseList> + <htmlTabRef>build-tab</htmlTabRef> + <htmlTabName>Build</htmlTabName> + <htmlTabIcon>wrench</htmlTabIcon> + <TestCaseRequestedList> + 010101 + </TestCaseRequestedList> + <TestCaseExclusionList></TestCaseExclusionList> + + <testCase id="010101"> + <class>Build_eNB</class> + <desc>Build eNB OCP (USRP)</desc> + <Build_eNB_args>-w USRP -c --eNBocp --ninja</Build_eNB_args> + </testCase> + +</testCaseList> 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 0000000000000000000000000000000000000000..7b4eacef3a3d091e7397bfc89a7f8422c459998c --- /dev/null +++ b/ci-scripts/xml_files/fr1_multi_node_build.xml @@ -0,0 +1,66 @@ +<!-- + + 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 + +--> +<testCaseList> + <htmlTabRef>build-tab</htmlTabRef> + <htmlTabName>Build</htmlTabName> + <htmlTabIcon>wrench</htmlTabIcon> + <TestCaseRequestedList> + 000001 000002 + 000003 000004 + </TestCaseRequestedList> + <TestCaseExclusionList></TestCaseExclusionList> + + <testCase id="000001"> + <class>Build_eNB</class> + <desc>Build eNB</desc> + <Build_eNB_args>-w USRP -c --eNB --ninja</Build_eNB_args> + <eNB_instance>0</eNB_instance> + <eNB_serverId>0</eNB_serverId> + <backgroundBuild>True</backgroundBuild> + </testCase> + + <testCase id="000004"> + <class>WaitEndBuild_eNB</class> + <desc>Wait for end of Build eNB</desc> + <eNB_instance>0</eNB_instance> + <eNB_serverId>0</eNB_serverId> + </testCase> + + <testCase id="000002"> + <class>Build_eNB</class> + <desc>Build gNB</desc> + <Build_eNB_args>-w USRP -c --gNB --ninja</Build_eNB_args> + <eNB_instance>1</eNB_instance> + <eNB_serverId>1</eNB_serverId> + <backgroundBuild>True</backgroundBuild> + </testCase> + + <testCase id="000003"> + <class>WaitEndBuild_eNB</class> + <desc>Wait for end of Build gNB</desc> + <eNB_instance>1</eNB_instance> + <eNB_serverId>1</eNB_serverId> + </testCase> + + +</testCaseList> 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 0000000000000000000000000000000000000000..cbaaf8ba9975a8e464424e0ff258e64a5b3aabac --- /dev/null +++ b/ci-scripts/xml_files/fr1_multi_node_terminate.xml @@ -0,0 +1,50 @@ +<!-- + + 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 + +--> +<testCaseList> + <htmlTabRef>test-fr1-tm1</htmlTabRef> + <htmlTabName>Test-FR1-TM1</htmlTabName> + <htmlTabIcon>tasks</htmlTabIcon> + <repeatCount>1</repeatCount> + <TestCaseRequestedList> + 070001 + 070000 + </TestCaseRequestedList> + <TestCaseExclusionList> + </TestCaseExclusionList> + + <testCase id="070000"> + <class>Terminate_eNB</class> + <desc>Terminate eNB</desc> + <eNB_instance>0</eNB_instance> + <eNB_serverId>0</eNB_serverId> + </testCase> + + <testCase id="070001"> + <class>Terminate_eNB</class> + <desc>Terminate gNB</desc> + <eNB_instance>1</eNB_instance> + <eNB_serverId>1</eNB_serverId> + </testCase> + +</testCaseList> + 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 0000000000000000000000000000000000000000..8c56f0bcec9354394dc622d86675e30ff1281dff --- /dev/null +++ b/ci-scripts/xml_files/fr1_multi_node_test.xml @@ -0,0 +1,77 @@ +<!-- + + 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 + +--> +<testCaseList> + <htmlTabRef>test-fr1-tm1</htmlTabRef> + <htmlTabName>Test-FR1-TM1</htmlTabName> + <htmlTabIcon>tasks</htmlTabIcon> + <repeatCount>1</repeatCount> + <TestCaseRequestedList> + 030000 + 040000 + 000001 + 070001 + 070000 + </TestCaseRequestedList> + <TestCaseExclusionList> + </TestCaseExclusionList> + + <testCase id="030000"> + <class>Initialize_eNB</class> + <desc>Initialize eNB</desc> + <Initialize_eNB_args>-O ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf</Initialize_eNB_args> + <eNB_instance>0</eNB_instance> + <eNB_serverId>0</eNB_serverId> + <air_interface>lte</air_interface> + </testCase> + + <testCase id="040000"> + <class>Initialize_eNB</class> + <desc>Initialize gNB (3/4 sampling rate)</desc> + <Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf -E</Initialize_eNB_args> + <eNB_instance>1</eNB_instance> + <eNB_serverId>1</eNB_serverId> + <air_interface>nr</air_interface> + </testCase> + + <testCase id="000001"> + <class>IdleSleep</class> + <desc>Sleep</desc> + <idle_sleep_time_in_sec>30</idle_sleep_time_in_sec> + </testCase> + + <testCase id="070000"> + <class>Terminate_eNB</class> + <desc>Terminate eNB</desc> + <eNB_instance>0</eNB_instance> + <eNB_serverId>0</eNB_serverId> + </testCase> + + <testCase id="070001"> + <class>Terminate_eNB</class> + <desc>Terminate gNB</desc> + <eNB_instance>1</eNB_instance> + <eNB_serverId>1</eNB_serverId> + </testCase> + +</testCaseList> + 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 0000000000000000000000000000000000000000..b2267efc77dcc514bcf07eda0c2223be3ed5b46a --- /dev/null +++ b/ci-scripts/xml_files/fr1_toggle_cots_ue.xml @@ -0,0 +1,39 @@ +<!-- + + 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 + +--> +<testCaseList> + <htmlTabRef>test-airplane-mode</htmlTabRef> + <htmlTabName>AirplaneToggle</htmlTabName> + <htmlTabIcon>tasks</htmlTabIcon> + <TestCaseRequestedList> + 010000 + </TestCaseRequestedList> + <TestCaseExclusionList></TestCaseExclusionList> + + <testCase id="010000"> + <class>COTS_UE_Airplane</class> + <desc>Toggle COTS Airplane mode ON</desc> + <cots_ue_airplane_args>ON</cots_ue_airplane_args> + </testCase> + + +</testCaseList> diff --git a/ci-scripts/xml_files/gnb_usrp_build.xml b/ci-scripts/xml_files/gnb_usrp_build.xml index 97d6ef06f6221875c6b25809d19af7fddb345bf6..e2662180c5b8fee0c2974e703328a30673eb5193 100644 --- a/ci-scripts/xml_files/gnb_usrp_build.xml +++ b/ci-scripts/xml_files/gnb_usrp_build.xml @@ -34,7 +34,7 @@ <mode>TesteNB</mode> <class>Build_eNB</class> <desc>Build gNB (USRP)</desc> - <Build_eNB_args>--gNB -w USRP</Build_eNB_args> + <Build_eNB_args>--gNB -w USRP --ninja</Build_eNB_args> <forced_workspace_cleanup>True</forced_workspace_cleanup> </testCase> diff --git a/ci-scripts/xml_files/nr_ue_usrp_build.xml b/ci-scripts/xml_files/nr_ue_usrp_build.xml index c3c842b85a9bb2974890cd9757de8ecb3a1172a4..bc04efdb4b8cd50ffd7905196f2f14b941db14ab 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 @@ <mode>TestUE</mode> <class>Build_OAI_UE</class> <desc>Build NR UE (USRP)</desc> - <Build_OAI_UE_args>--nrUE -w USRP</Build_OAI_UE_args> + <Build_OAI_UE_args>--nrUE -w USRP --ninja</Build_OAI_UE_args> <clean_repository>false</clean_repository> </testCase> diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 7e59f38e8d88804e5ffc9de590388e48ef66f8a9..38dbd3fd5228ca6cd405a57778b6ebe1c8f3a9f1 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) @@ -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 88b8811575bac560410f84275cef6272352900c6..36af9eaee4cd3538d1a8914a55b0ebb34b3bfa27 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 22933fdd5be749b45f207f68272d9f8958be5cb2..1680410ebb5294041eab45b1191922dda0feecc7 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 06a5d350c75a452ef18e325813de53453912d66d..03f7af99bc2ca9cc8d81c7f834f7ad8dd2a2c7ce 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -53,6 +53,7 @@ #include <sys/resource.h> #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 <readline/history.h> @@ -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 debb9f02ec962c63e798273bb19c481eff38f5c7..b66641d5c8b9588b8699c93b31326b5a418f5252 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 cbb2dbe3d91742afc2375ff3fd48f90b20c48404..e1446f15d71a70d374851ba9cfa5f4707590c58b 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 e507050239767f9d1b602486b8214d5dcc676b20..a16b4dbe136034d7f7cc4ae33555016a4b448e0a 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,16 +79,16 @@ 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 \<conf file\> -Some config examples can be found in the following folder: -https://gitlab.eurecom.fr/oai/openairinterface5g/-/tree/develop/targets/PROJECTS/GENERIC-LTE-EPC/CONF +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) -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) +These files have to be updated manually to set the IP addresses and frequency. -TO DO : attach base confif files -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 ffa44bd978758cc13923499970ff8743e938543f..d2d64d09593b9a27464d1dd232ecd9e2428f350a 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 e4e42b4f23b069c053be31d02d5c4d6f289534e9..2d96d40c75e78717baa6f7d2c23fd5ad3bb9d9b7 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -1167,6 +1167,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); diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index bf77125975cf992b42b1b86bf37847c126dd815b..95d57a535ac5ac07ddd66c62e71432d7636c7ffc 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 <openair2/GNB_APP/gnb_app.h> - +#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); + @@ -817,7 +820,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 +961,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 d113ae45aacc331fb96e6dfe739830d4326891f2..d6cfe6b906acef4026dcf08d7b03433b32fd1986 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-uesoftmodem.c b/executables/nr-uesoftmodem.c index 6d3bbc903859b653c2d895273db5fb8e45b27a91..fa816b506c0b3d5111b225068487c30a9f29834e 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 <openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h> #include <openair1/SCHED_NR_UE/fapi_nr_ue_l1.h> +/* 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 <executables/nr-uesoftmodem.h> #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<MAX_NUM_CCs; CC_id++) { diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 43b921001afd4aff210083f96e5a547da5033f90..418ed54fc6871fc7358c417dfc53bd8457836fae 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -61,19 +61,11 @@ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0,TYPE_UINT64, 0}, \ - {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ - {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:&do_forms, defintval:0, TYPE_INT, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 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}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ {"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, iptr:&vcdflag, defintval:0, TYPE_INT, 0}, \ - {"numerology" , CONFIG_HLP_NUMEROLOGY, 0, 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}, \ {"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \ {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&UE_no_timing_correction, defintval:0, TYPE_INT, 0}, \ diff --git a/executables/split_headers.h b/executables/split_headers.h index 4e328f74c418c7f902014b99630dd4fbe2130e7a..985b1b7daebe98ecec8731fbef27d033cc57ef7d 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -28,6 +28,7 @@ #include <stdint.h> #include <stdbool.h> #include <openair1/PHY/defs_eNB.h> +#include <common/utils/telnetsrv/telnetsrv_proccmd.h> #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 c8624e9e91d27c094ff88e8b55f14212ae4c3341..f84917f12e4bc8bc4057e39762bb0c3d98f90a31 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 @@ -1120,6 +1120,7 @@ typedef struct uint16_t ul_dmrs_symb_pos; uint8_t dmrs_config_type; uint16_t ul_dmrs_scrambling_id; + uint16_t pusch_identity; uint8_t scid; uint8_t num_dmrs_cdm_grps_no_data; uint16_t dmrs_ports;//DMRS ports. [TS38.212 7.3.1.1.2] provides description between DCI 0-1 content and DMRS ports. Bitmap occupying the 11 LSBs with: bit 0: antenna port 1000 bit 11: antenna port 1011 and for each bit 0: DMRS port not used 1: DMRS port used diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c index daa23460987445274babe7919f10202fb243847a..42d500ae8670f509e3ccecde96558d0e102d8fcd 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c @@ -197,8 +197,10 @@ decoder_node_t *add_nodes(int level, int first_leaf_index, t_nrPolar_params *pol } for (int i=0;i<Nv;i++) { - if (polarParams->information_bit_pattern[i+first_leaf_index]>0) - all_frozen_below=0; + if (polarParams->information_bit_pattern[i+first_leaf_index]>0) { + all_frozen_below=0; + break; + } } if (all_frozen_below==0) diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index ce409de1318460a5e4cb3f5a5cf2c17d6aaff15a..8de011acef3a3cdf9d31f3880cc6063bc998693b 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -2006,11 +2006,6 @@ void fill_ulsch(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_ulsch_pdu *ulsch_pdu return; } - //AssertFatal(ulsch->harq_processes[harq_pid]->nb_rb>0,"nb_rb = 0\n"); - if(ulsch->harq_processes[harq_pid]->nb_rb == 0) { - LOG_E(PHY, "fill_ulsch UE_id %d nb_rb = 0\n", UE_id); - } - ulsch->harq_processes[harq_pid]->frame = frame; ulsch->harq_processes[harq_pid]->subframe = subframe; ulsch->harq_processes[harq_pid]->handled = 0; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c index e4083863f0da352bfd5c74998414cbd768526601..ab7c2b90910d4df9eff3fe17d0139843bd73038c 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/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 2640a86240bba7abe906e54dc91530b75ff26e92..d36dd6772bf7e0934172907329de3ddc15b911a5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -540,7 +540,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_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 7f941e55672a40992070b66eb6f2aea8ab20c66a..a8827b4e92c7cb386fdb483168aab5bb0f0b3067 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -214,7 +214,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", dlsch1_harq->codeword); #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); @@ -224,14 +225,16 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, break; default: - AssertFatal(1 == 0, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type); + LOG_E(PHY, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type); return(-1); break; } - 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); diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index dfb148d34e84c3c61e7c17ecc6679414c1931aae..5aff1ac48a2b64097b358f540b7b970d7441fd87 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -26,6 +26,7 @@ #include <stdlib.h> #include "nr_phy_scope.h" #include "executables/nr-softmodem-common.h" +#include "executables/softmodem-common.h" #include <forms.h> #define TPUT_WINDOW_LENGTH 100 @@ -768,6 +769,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 +805,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 429537141a60f0cfba9753faf820348792062abc..84b9e66908bec48d048e3cee9f345ae5726cc1fd 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 835fb4ea7b2a028f4ddfb378c3c877b699b6bc27..af237b2325e8a3f2fc035478cff4df4f39974901 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 779a57a7202450327cc8d515066191f48e373613..adf04d5ea4a6a7f664e23eab35c8bff82d46121e 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 0000000000000000000000000000000000000000..f6671acc6df14e006c428e6b603d01eced07daa3 --- /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 a74d148479d2158aa668416f36f97309272b8bb6..5e2be8bd8f76181ff7f660da8902ab2d1bf88415 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 1843d8d5bcd75a8b2ccdf4a4abc9facf50100490..baa64561f0e4bc5fc8b3dd0f2bc67788e3a10b78 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 ddebcc3e067e83d03c7ca33ac7164ad329670936..2870f1d42e0594bbe198afa0e9e91861886dc938 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -160,6 +160,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ gNB->dlsch[i][0]->harq_mask=0; } gNB->pdcch_pdu = NULL; + gNB->ul_dci_pdu = NULL; gNB->pbch_configured=0; for (int i=0;i<number_dl_pdu;i++) { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 992c908c5d2e4572f61ccdc80c9ca7b9839c6d75..94e356951aa916e105fe39f04a291a134d2425dc 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -424,7 +424,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) for (int ULSCH_id=0;ULSCH_id<NUMBER_OF_NR_ULSCH_MAX;ULSCH_id++) { NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id][0]; int harq_pid; - int no_sig; + //int no_sig; NR_UL_gNB_HARQ_t *ulsch_harq; if ((ulsch) && diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index 41d8551e75726427f356cc0a78226723ad8bd1ff..f97b9dfb78a1d7bdebd35c8324d1ecac635b3936 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","<predef,current>",channelmod_show_cmd}, + {"modify","<channelid> <param> <value>",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; i<nb_taps; i++) @@ -129,10 +135,9 @@ void fill_channel_desc(channel_desc_t *chan_desc, if (R_sqrt == NULL) { chan_desc->R_sqrt = (struct complex **) calloc(nb_taps,sizeof(struct complex *)); - + chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_NTAPS ; for (i = 0; i<nb_taps; i++) { - chan_desc->R_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; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_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; i<nb_taps; i++) { //chan_desc->R_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 epa_delays[] = { 0,.03,.07,.09,.11,.19,.41}; @@ -277,14 +282,26 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, SCM_t channel_model, double sampling_rate, double channel_bandwidth, - double forgetting_factor, + 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; i<max_chan;i++) { + if (defined_channels[i] == NULL) { + defined_channels[i]=chan_desc; + chan_desc->chan_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; @@ -313,7 +330,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; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -351,9 +368,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; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { chan_desc->R_sqrt[i][j].x = 1.0; chan_desc->R_sqrt[i][j].y = 0.0; @@ -372,7 +390,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; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -410,6 +428,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)); @@ -423,14 +442,14 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, } break; - + 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; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -449,7 +468,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->ch[i] = (struct complex *) malloc(chan_desc->channel_length * sizeof(struct complex)); - + for (i = 0; i<nb_tx*nb_rx; i++) chan_desc->chF[i] = (struct complex *) malloc(1200 * sizeof(struct complex)); @@ -463,7 +482,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)); @@ -484,7 +503,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; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -530,7 +549,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; @@ -538,7 +557,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; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -592,7 +611,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; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -646,7 +665,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; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -679,8 +698,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; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) { @@ -700,7 +719,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; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*etu_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -733,7 +752,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)); @@ -754,7 +773,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; i<chan_desc->nb_taps; i++) { chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]); sum_amps += chan_desc->amps[i]; @@ -781,7 +800,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)); @@ -1292,10 +1311,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; i<ch->nb_tx*ch->nb_rx; i++) { + free(ch->ch[i]); + free(ch->chF[i]); + } + + for (int i = 0; i<ch->nb_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; i<ch->nb_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) { @@ -1408,11 +1454,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; l<desc->nb_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; @@ -1436,7 +1482,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; @@ -1488,22 +1534,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 <model index> <param name> <param value>: set the specified parameters in a current model to the given value\n"); + prnt(" <model index> specifies the model, the show current model command can be used to list the current models indexes\n"); + prnt(" <param name> 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; i<cd->nb_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); + + 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 0; + 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; } @@ -1519,6 +1668,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 6071e1e74387ab7f54d38c57fa306520649ef113..cc06e2f85c784ad0b196c3be29f40a695389cfeb 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 { @@ -214,8 +232,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" @@ -273,9 +292,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 603ff25198346adb446ba047b1525efbc4b1ec7d..f1daacbb650225f681330339e8870603d8a73b2d 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); } -} -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 */ - } + Protocol__FlexCellConfig helper; + helper.slice_config = slice_config; + flexran_agent_destroy_mac_slice_config(&helper); } -void flexran_agent_slice_update(mid_t mod_id) -{ - int i; - int changes = 0; +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; - if (perform_slice_config_update_count <= 0) return; - perform_slice_config_update_count--; + 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; - pthread_mutex_lock(&sc_update_mtx); + 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 (!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; + 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"); } +} - /********* 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]); - } - 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]); - } +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; - /********* 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); + 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); - /* 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 (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"); } - 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); +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); + + 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); } - pthread_mutex_unlock(&sc_update_mtx); - return config; + 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); + } } 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 2f9f99c740bd49791f2cc917f288f394b78ca5ce..5a8d4f31aa70809c79c613b13ea91ad01ade528c 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 a85cbac5439465b3ca9d88e2a21241a67bb72ab9..93de0b11ec3d1c228b85bae254b24c559ecc7bab 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); +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 { + 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); } } -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]); +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 { + 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); } - 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 apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *dl) { + if (!dl) + return; -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; + 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); } - 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; + /* 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; } - 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]; + 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]); } } - 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]; + 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; } } - 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"); +void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *ul) { + if (!ul) 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); - } 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; + 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; } - - /* 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]); + 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; } - } else { - LOG_E(FLEXRAN_AGENT, "[%d] DL slice verification failed, refusing application\n", mod_id); + 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]); } } - verified = 1; - if (sup->n_ul == 0) { - LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_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; + if (ul->scheduler) { + if (ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); + return; } - - /* 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, "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; } } - 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) +int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) { - /* 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); - return; - } 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); - } + 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); } - 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); - } + } + 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); } } - n_ue_slice_assoc_updates = 0; - return changes; + 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 957fe6065edfee892de34e17c436cbc84a275fc5..9db5d61a11693ca899811628d9eb18d7592f716d 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 67329e91be0d9508c5943dd527dfb990ef654201..6e54e155c260cb86d5358298409e26691ca8910a 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 a8f4030d3664be1e1388d8d42cae8feed9a4dd90..c9e66b6f88236c9410f19a429ca916fafdf07f20 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 04a47406e1b9d6e7f58acd9ae9da94a4d3dbff63..c2d7cb9e552bc0746b307a1af0bc57367b01d8f3 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 1cca6ac9c15e0a26d59b2b832fdd361d31c65de8..006eaa1d3ca67f571fd764409d930af620394b9e 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 55ce9d5059eee1bf682b1cf8a82e6796bb2a8fdf..fcee6142f0bc7cce1a0cec70f4b19e93267e669a 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 733d883c92c0ed5af68e848051e6d2783ff937d6..2f2267b62815ac3891981a0088355c2423112410 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_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 -} - -enum flex_dl_accounting_policy { - POL_FAIR = 0; - POL_GREEDY = 1; - POL_NUM = 2; -} - -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; +enum flex_slice_algorithm { + None = 0; + Static = 1; + NVS = 2; +} + +message flex_slice_static { + optional uint32 posLow = 1; + optional uint32 posHigh = 2; +} + +message flex_slice { + optional uint32 id = 1; + optional string label = 2; + optional string scheduler = 3; + oneof params { + flex_slice_static static = 10; + } +} + +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 324153613d396307e3a37bce643bdcb60220e19e..1a69deec7146e2941e91f0f894ee9d7c680d97c7 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 0e1c7e64bc8025ad5358f952ed2800c71ebbac32..7c91e57813d2b63734b17daf6cc116e46f7d8915 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 2200c8f0135f27cc5c8abcd4d5e5d51a187e6a1b..1d189832b473f0314c2c3946ebfb48364de8b162 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -29,6 +29,7 @@ #include <string.h> #include <inttypes.h> +#include <dlfcn.h> #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 dc320ef974731a4dd1542989ffd81e5a685830c4..7569ca1ac155e45f9cb8dd831c7599c54372a53b 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 5f17cf4841e327c9e7355b28623cdf849458a8b8..2a5930e1a8b5dd9a18704c04d2df7e2ae777572b 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 32cb8c74e18d0cde3f657a4dd4e8246ae752ccfe..79c992a4d7ce678609544616db7187e984f453c3 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; - - 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; -} - -void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { - 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 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; -} - -void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { - 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 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, 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; -} +Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id) { + if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None; -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; + 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; } - - 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; - //} +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; } -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; +Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id) { + if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None; - RC.mac[mod_id]->slice_info.intraslice_share_active = intraslice_active; + 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_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; +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; - RC.mac[mod_id]->slice_info.interslice_share_active = interslice_active; + 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; } -slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx) { +int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { 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; + 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; } -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) { +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; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pct = percentage / 100.0f; + 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_dl_slice_isolation(mid_t mod_id, int slice_idx) { +int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - - 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; + 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; } -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) { +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; - - RC.mac[mod_id]->slice_info.dl[slice_idx].prio = priority; + 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_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; +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); } -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_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_get_dl_slice_position_high(mid_t mod_id, int slice_idx) { +int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) { 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; + 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_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) { +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; - - 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; - } + 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; } - - 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; +int flexran_get_num_dl_slices(mid_t mod_id) { + if (!mac_is_present(mod_id)) return 0; + if (!RC.mac[mod_id]->pre_processor_dl.slices) return 0; + return RC.mac[mod_id]->pre_processor_dl.slices->num; } -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; - +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: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; + break; } -} -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; + 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); } -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) { +int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { 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; -} - -int flexran_create_ul_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_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; + 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; - - 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) { +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; + } - 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; +int flexran_get_num_ul_slices(mid_t mod_id) { + 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; } -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; +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; } -int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx) { +int flexran_set_dl_scheduler(mid_t mod_id, char *sched) { 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; + 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_slice_scheduler(mid_t mod_id, int slice_idx) { +char *flexran_get_ul_scheduler_name(mid_t mod_id) { if (!mac_is_present(mod_id)) return NULL; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name; + return RC.mac[mod_id]->pre_processor_ul.ul_algo.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]->slice_info.ul[slice_idx].sched_name) - free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_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_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 ce328838529508ba3e65153e83171ab2d0a7c978..2d8a86f7d01de163f08c524ae80d2cbede17b81b 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 c46005ee2d5f28935f3dfe6a806e718718ef7fd1..d184c7e439a89d1decfce1b4eca734d0f9e31f33 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; ii<MAX_MOBILES_PER_ENB; ii++) { LTE_eNB_ULSCH_t *ulsch = RC.eNB[module_idP][CC_id]->ulsch[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 7621994ab2e1f247011f7ea7d03db1ef298d32be..1f99f50ece2019987b4b2e47dd8fe7bd68a46201 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_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 78d6f6a3d76574d1b8ab70d96184b5e5297095c0..89c2ecc83d28bb9f04d06e57f7c31ec9c15a4268 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 3062e5c9647826af5fe547d5fa7a06c7f6707004..2de45db8565e47aacecbee004b0a315fdec903df 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 329e262c828e1008c4f74c712f91684ac1ec0ce4..faefc481f65b393e70763202a2d3845764c3216c 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*/ @@ -1172,107 +1165,88 @@ typedef struct { } UE_free_list_t; /** - * slice specific scheduler for the DL + * describes contiguous RBs */ -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; - + int start; + int length; +} contig_rbs_t; +/** + * definition of a scheduling algorithm implementation used in the + * default DL scheduler + */ 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; + 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; /** - * describes contiguous RBs + * definition of a scheduling algorithm implementation used in the + * default UL scheduler */ typedef struct { - int start; - int length; -} contig_rbs_t; + 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 { @@ -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 2cb86c25af221c003757dc961f51a8b7eea9c5f0..9d49fdffd5d7e5cb451b7346b7a0128a3f9c2ee6 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 1a88623a1f3d31396cc362dbaff22a65caa279ea..af6d1a7ac355b8fe4182c48bfde08ce53445566d 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 4f3baf17831a5f5baf8330f77a8fba49854b86a6..6477d600215f5c75d5e23c5e6385078be4188fc3 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -69,32 +69,47 @@ 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. - for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + /* 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); @@ -103,14 +118,14 @@ int round_robin_dl(module_id_t Mod_id, 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; + 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); - continue; + 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 @@ -119,12 +134,12 @@ int round_robin_dl(module_id_t Mod_id, 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; + 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) - continue; // cannot allocate CCE + goto skip_ue; // cannot allocate CCE ue_ctrl->pre_dci_dl_pdu_idx = idx; // retransmissions: directly allocate n_rbg_sched -= nb_rbg; @@ -133,6 +148,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 +166,390 @@ 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) { + *cur_UE = UE_id; + cur_UE = &UE_sched.next[UE_id]; + } } - } - if (num_ue_req == 0) +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: 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); + // 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); - num_ue_req--; - max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); - UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate continue; } UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; - *cur_UE = UE_id; - cur_UE = &UE_sched.next[UE_id]; - rb_required_total += rb_required[UE_id]; - num_ue_sched++; - UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate + 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; + *cur_UE = -1; // not all UEs might be allocated, mark end /* 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; + 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; - rb_required_total -= sRBG; - if (rb_required_total <= 0) - break; + 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 */ ; } - /* if not all UEs could be allocated in this round */ - if (num_ue_req > max_num_ue) { - /* go to the first one we missed */ - for (int i = 0; i < max_num_ue; ++i) - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); - } else { - /* else, just start with the next UE next time */ - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); + return n_rbg_sched; +} +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]; + 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; + *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 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; + + 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 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 0000000000000000000000000000000000000000..9c88f6cffbbbb723756b97558dc93c31a16353eb --- /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 <stdlib.h> +#include <dlfcn.h> + +#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 0000000000000000000000000000000000000000..1099b50ea0cb92533d14a1bfa57945de0deefcb9 --- /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 0000000000000000000000000000000000000000..744f8924d925ed81de1d30883e6e44e4d2fbbfb8 --- /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_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 591c2448b8486dc34e3b29a340aa39944002b0b9..d8583167dd5e1a193fcda6ad7c84e86ad974f046 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -251,9 +251,8 @@ typedef struct { uint8_t short_messages; //8 bits uint8_t tb_scaling; //2 bits uint8_t pucch_resource_indicator; //3 bits - uint8_t dmrs_sequence_initialization; //1 bit uint8_t system_info_indicator; //1 bit - + uint8_t ulsch_indicator; uint8_t slot_format_indicator_count; uint8_t *slot_format_indicators; @@ -290,6 +289,7 @@ typedef struct { dci_field_t cloded_loop_indicator; //variable dci_field_t ul_sul_indicator; //variable dci_field_t antenna_ports; //variable + dci_field_t dmrs_sequence_initialization; dci_field_t reserved; //1_0/C-RNTI:10 bits, 1_0/P-RNTI: 6 bits, 1_0/SI-&RA-RNTI: 16 bits } dci_pdu_rel15_t; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 074908022cea17dcd4ced419e57cc3b7d548867c..f40d822b6bff1e72d1316a55801e8b261605f60c 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -31,6 +31,7 @@ */ #include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include <limits.h> const uint8_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160}; @@ -1879,7 +1880,8 @@ uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB) { return 1; } -uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, +uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu_rel15_t *dci_pdu, nr_dci_format_t format, nr_rnti_type_t rnti_type, @@ -1887,9 +1889,15 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, int bwp_id) { uint16_t size = 0; + uint16_t numRBG = 0; + long rbg_size_config; + int num_entries = 0; + int pusch_antenna_ports = 1; // TODO hardcoded number of antenna ports for pusch NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; NR_PDSCH_Config_t *pdsch_config = bwp->bwp_Dedicated->pdsch_Config->choice.setup; + NR_PUSCH_Config_t *pusch_Config = ubwp->bwp_Dedicated->pusch_Config->choice.setup; + NR_SRS_Config_t *srs_config = ubwp->bwp_Dedicated->srs_Config->choice.setup; switch(format) { /*Only sizes for 0_0 and 1_0 are correct at the moment*/ @@ -1897,30 +1905,199 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, /// fixed: Format identifier 1, Hop flag 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2 Time Domain assgnmt 4 --20 size += 20; size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment -- hopping scenario to be updated - size += nr_dci_size(secondaryCellGroup,dci_pdu,NR_DL_DCI_FORMAT_1_0, rnti_type, N_RB, bwp_id) - size; // Padding to match 1_0 size + size += nr_dci_size(scc,secondaryCellGroup,dci_pdu,NR_DL_DCI_FORMAT_1_0, rnti_type, N_RB, bwp_id) - size; // Padding to match 1_0 size // UL/SUL indicator assumed to be 0 break; case NR_UL_DCI_FORMAT_0_1: - /// fixed: Format identifier 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2, SRS request 2 --17 - size += 17; + /// fixed: Format identifier 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2, ULSCH indicator 1 --16 + size += 16; // Carrier indicator + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) { + dci_pdu->carrier_indicator.nbits=3; + size += dci_pdu->carrier_indicator.nbits; + } // UL/SUL indicator + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink != NULL) { + dci_pdu->carrier_indicator.nbits=1; + size += dci_pdu->ul_sul_indicator.nbits; + } // BWP Indicator + uint8_t n_ul_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; + if (n_ul_bwp < 2) + dci_pdu->bwp_indicator.nbits = n_ul_bwp; + else + dci_pdu->bwp_indicator.nbits = 2; + size += dci_pdu->bwp_indicator.nbits; // Freq domain assignment + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pusch_Config->choice.setup->rbg_Size != NULL) + rbg_size_config = 1; + else + rbg_size_config = 0; + numRBG = getNRBG(NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275), + NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275), + rbg_size_config); + if (pusch_Config->resourceAllocation == 0) + dci_pdu->frequency_domain_assignment.nbits = numRBG; + else if (pusch_Config->resourceAllocation == 1) + dci_pdu->frequency_domain_assignment.nbits = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); + else + dci_pdu->frequency_domain_assignment.nbits = ((int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )>numRBG) ? (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )+1 : numRBG+1; + size += dci_pdu->frequency_domain_assignment.nbits; // Time domain assignment - // VRB to PRB mapping + if (pusch_Config->pusch_TimeDomainAllocationList==NULL) { + if (ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList==NULL) + num_entries = 16; // num of entries in default table + else + num_entries = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count; + } + else + num_entries = pusch_Config->pusch_TimeDomainAllocationList->choice.setup->list.count; + dci_pdu->time_domain_assignment.nbits = (int)ceil(log2(num_entries)); + size += dci_pdu->time_domain_assignment.nbits; // Frequency Hopping flag + if ((pusch_Config->frequencyHopping!=NULL) && (pusch_Config->resourceAllocation != NR_PUSCH_Config__resourceAllocation_resourceAllocationType0)) { + dci_pdu->frequency_hopping_flag.nbits = 1; + size += 1; + } // 1st DAI + if (secondaryCellGroup->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook==NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic) + dci_pdu->dai[0].nbits = 2; + else + dci_pdu->dai[0].nbits = 1; + size += dci_pdu->dai[0].nbits; // 2nd DAI + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { //TODO not sure about that + dci_pdu->dai[1].nbits = 2; + size += dci_pdu->dai[1].nbits; + } // SRS resource indicator + if (pusch_Config->txConfig != NULL){ + int count=0; + if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){ + for (int i=0; i<srs_config->srs_ResourceSetToAddModList->list.count; i++) { + if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_codebook) + count++; + } + if (count>1) { + dci_pdu->srs_resource_indicator.nbits = 1; + size += dci_pdu->srs_resource_indicator.nbits; + } + } + else { + int lmin,Lmax = 0; + int lsum = 0; + if ( secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig != NULL) { + if ( secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers != NULL) + Lmax = *secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers; + else + AssertFatal(1==0,"MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n"); + } + else + AssertFatal(1==0,"MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n"); + for (int i=0; i<srs_config->srs_ResourceSetToAddModList->list.count; i++) { + if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_nonCodebook) + count++; + if (count < Lmax) lmin = count; + else lmin = Lmax; + for (int k=1;k<=lmin;k++) { + lsum += binomial(count,k); + } + } + dci_pdu->srs_resource_indicator.nbits = (int)ceil(log2(lsum)); + size += dci_pdu->srs_resource_indicator.nbits; + } + } // Precoding info and number of layers + long transformPrecoder; + if (pusch_Config->transformPrecoder == NULL){ + // if transform precoder is null, apply the values from msg3 + if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) + transformPrecoder = 1; + else + transformPrecoder = 0; + } + else + transformPrecoder = *pusch_Config->transformPrecoder; + if (pusch_Config->txConfig != NULL){ + if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){ + if (pusch_antenna_ports > 1) { + if (pusch_antenna_ports == 4) { + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank>1)) + dci_pdu->precoding_information.nbits = 6-(*pusch_Config->codebookSubset); + else { + if(*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) + dci_pdu->precoding_information.nbits = 2; + else + dci_pdu->precoding_information.nbits = 5-(*pusch_Config->codebookSubset); + } + } + else { + AssertFatal(pusch_antenna_ports==2,"Not valid number of antenna ports"); + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank==2)) + dci_pdu->precoding_information.nbits = 4-(*pusch_Config->codebookSubset); + else + dci_pdu->precoding_information.nbits = 3-(*pusch_Config->codebookSubset); + } + } + } + } + size += dci_pdu->precoding_information.nbits; // Antenna ports + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = NULL; + int xa=0; + int xb=0; + if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL){ + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; + xa = ul_ant_bits(NR_DMRS_UplinkConfig,transformPrecoder); + } + if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL){ + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + xb = ul_ant_bits(NR_DMRS_UplinkConfig,transformPrecoder); + } + if (xa>xb) + dci_pdu->antenna_ports.nbits = xa; + else + dci_pdu->antenna_ports.nbits = xb; + size += dci_pdu->antenna_ports.nbits; + // SRS request + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink==NULL) + dci_pdu->srs_request.nbits = 2; + else + dci_pdu->srs_request.nbits = 3; + size += dci_pdu->srs_request.nbits; // CSI request + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig != NULL) { + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup->reportTriggerSize != NULL) { + dci_pdu->csi_request.nbits = *secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup->reportTriggerSize; + size += dci_pdu->csi_request.nbits; + } + } // CBGTI + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { + int num = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->codeBlockGroupTransmission->choice.setup->maxCodeBlockGroupsPerTransportBlock; + dci_pdu->cbgti.nbits = 2 + (num<<1); + size += dci_pdu->cbgti.nbits; + } // PTRS - DMRS association + if ( (NR_DMRS_UplinkConfig->phaseTrackingRS == NULL && transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) || + transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled || (*pusch_Config->maxRank==1) ) + dci_pdu->ptrs_dmrs_association.nbits = 0; + else + dci_pdu->ptrs_dmrs_association.nbits = 2; + size += dci_pdu->ptrs_dmrs_association.nbits; // beta offset indicator + if (pusch_Config->uci_OnPUSCH!=NULL){ + if (pusch_Config->uci_OnPUSCH->choice.setup->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_dynamic) { + dci_pdu->beta_offset_indicator.nbits = 2; + size += dci_pdu->beta_offset_indicator.nbits; + } + } // DMRS sequence init + if (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) { + dci_pdu->dmrs_sequence_initialization.nbits = 1; + size += dci_pdu->dmrs_sequence_initialization.nbits; + } break; case NR_DL_DCI_FORMAT_1_0: @@ -1946,10 +2123,10 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu->bwp_indicator.nbits = 2; size += dci_pdu->bwp_indicator.nbits; // Freq domain assignment - long rbg_size_config = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rbg_Size; - uint16_t numRBG = getNRBG(NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), - NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), - rbg_size_config); + rbg_size_config = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rbg_Size; + numRBG = getNRBG(NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), + NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), + rbg_size_config); if (pdsch_config->resourceAllocation == 0) dci_pdu->frequency_domain_assignment.nbits = numRBG; else if (pdsch_config->resourceAllocation == 1) @@ -1958,7 +2135,6 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu->frequency_domain_assignment.nbits = ((int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )>numRBG) ? (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )+1 : numRBG+1; size += dci_pdu->frequency_domain_assignment.nbits; // Time domain assignment (see table 5.1.2.1.1-1 in 38.214 - int num_entries; if (pdsch_config->pdsch_TimeDomainAllocationList==NULL) { if (bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList==NULL) num_entries = 16; // num of entries in default table @@ -2068,6 +2244,27 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, return size; } +int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrecoder) { + + uint8_t type,maxl; + if(NR_DMRS_UplinkConfig->dmrs_Type == NULL) + type = 1; + else + type = 2; + if(NR_DMRS_UplinkConfig->maxLength == NULL) + maxl = 1; + else + maxl = 2; + if (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) + return( maxl+type+1); + else { + if (type==1) + return (maxl<<1); + else + AssertFatal(1==0,"DMRS type not valid for this choice"); + } +} + int tdd_period_to_num[8] = {500,625,1000,1250,2000,2500,5000,10000}; int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) { @@ -2208,3 +2405,20 @@ int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,i AssertFatal(1==0,"Shouldn't get here\n"); return(-1); } + + +int binomial(int n, int k) { + int c = 1, i; + + if (k > n-k) + k = n-k; + + for (i = 1; i <= k; i++, n--) { + if (c/i > UINT_MAX/n) // return 0 on overflow + return 0; + + c = c / i * n + c % i * n / i; + } + return c; +} + diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 2f7f1449830a8426b3453dfbbd4ae57818b05660..a5e38bf128ef95029970069d88414bdeaace756a 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -77,7 +77,8 @@ int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); -uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, +uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu_rel15_t *dci_pdu, nr_dci_format_t format, nr_rnti_type_t rnti_type, @@ -103,6 +104,8 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, uint8_t nb_preambles, uint8_t unpaired); +int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPrecoder); + int get_format0(uint8_t index, uint8_t unpaired); uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 56ae14f98b8760d0708ebf9684a3b6fa060da999..840aafa943043c428c0522b4f138cd0f12f658ab 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -360,7 +360,7 @@ 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"); 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 a79b4083e31429380a0dde40974a1c2a8f61bd92..53263747fc3363b5983f7628bd95a84816c75026 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -223,7 +223,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl 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(mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); + 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; @@ -243,7 +243,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl 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(mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); + 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]; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 109d4570f43e3ba140b044e4051d53acfdd9cded..47b420d39bb123e75c93b3412f1cc0baf6beba89 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -773,8 +773,8 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in uint16_t rnti = 0x1234; uint32_t rb_size = 50; uint32_t rb_start = 0; - uint8_t nr_of_symbols = 12; - uint8_t start_symbol_index = 2; + 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; @@ -2235,9 +2235,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); @@ -2345,10 +2350,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 +2424,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,9 +2755,8 @@ 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, @@ -2872,8 +2874,8 @@ 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, @@ -3142,7 +3144,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 @@ -3530,7 +3532,7 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, dci_pdu_rel15->cbgfi.val = (*dci_pdu>>(dci_size-pos))&((1<<dci_pdu_rel15->cbgfi.nbits)-1); // DMRS sequence init pos+=1; - dci_pdu_rel15->dmrs_sequence_initialization = (*dci_pdu>>(dci_size-pos))&0x1; + dci_pdu_rel15->dmrs_sequence_initialization.val = (*dci_pdu>>(dci_size-pos))&0x1; break; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index db93734a7ddc11d9315212fd1bc9e4bad3bf1594..2eb4ad498bb8e2d40130bc6edf7872e7ce13b1f3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -688,7 +688,7 @@ void nr_generate_Msg2(module_id_t module_idP, pdcch_pdu_rel15->StartSymbolIndex, pdcch_pdu_rel15->DurationSymbols); - fill_dci_pdu_rel15(secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id); + fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id); dl_req->nPDUs+=2; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 338c94776b04f37925134db32e2ce782670e14dd..8841083796b3034b9a09d2a5ca494e144c4ef6ed 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -329,7 +329,7 @@ int configure_fapi_dl_pdu(int Mod_idP, pdsch_pdu_rel15->rbStart = (rbStart!=NULL) ? *rbStart : 0; pdsch_pdu_rel15->rbSize = (rbSize!=NULL) ? *rbSize : pdsch_pdu_rel15->BWPSize; pdsch_pdu_rel15->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP - // choose shortest PDSCH + int startSymbolAndLength=0; int time_domain_assignment=2; int StartSymbolIndex,NrOfSymbols; @@ -362,10 +362,10 @@ int configure_fapi_dl_pdu(int Mod_idP, AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); // time domain assignment dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; // row index used here instead of SLIV; - // mcs ndi and rv + // mcs and rv dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0]; dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0]; - // harq pid + // harq pid and ndi dci_pdu_rel15[0].harq_pid = current_harq_pid; dci_pdu_rel15[0].ndi = UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].ndi; // DAI @@ -381,7 +381,8 @@ int configure_fapi_dl_pdu(int Mod_idP, UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].is_waiting = 1; // antenna ports dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0 - + // dmrs sequence initialization + dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID; LOG_D(MAC, "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n", dci_pdu_rel15[0].frequency_domain_assignment.val, pdsch_pdu_rel15->rbStart, @@ -437,7 +438,7 @@ int configure_fapi_dl_pdu(int Mod_idP, rnti_types[0] = NR_RNTI_C; - fill_dci_pdu_rel15(secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,bwp_id); + fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,bwp_id); LOG_D(MAC, "DCI params: rnti %x, rnti_type %d, dci_format %d\n \ coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", @@ -468,22 +469,70 @@ int configure_fapi_dl_pdu(int Mod_idP, return TBS; //Return TBS in bytes } -void config_uldci(NR_BWP_Uplink_t *ubwp,nfapi_nr_pusch_pdu_t *pusch_pdu,nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, int *rnti_types) { - - dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, - pusch_pdu->rb_start, - NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); +void config_uldci(NR_BWP_Uplink_t *ubwp, + nfapi_nr_pusch_pdu_t *pusch_pdu, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + dci_pdu_rel15_t *dci_pdu_rel15, + int *dci_formats, int *rnti_types, + int time_domain_assignment, + int n_ubwp, int bwp_id) { + + switch(dci_formats[(pdcch_pdu_rel15->numDlDci)-1]) { + case NR_UL_DCI_FORMAT_0_0: + dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, + pusch_pdu->rb_start, + NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); + + dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; + dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; + dci_pdu_rel15->mcs = 9; + + dci_pdu_rel15->format_indicator = 0; + dci_pdu_rel15->ndi = 1; + dci_pdu_rel15->rv = 0; + dci_pdu_rel15->harq_pid = 0; + dci_pdu_rel15->tpc = 2; + break; + case NR_UL_DCI_FORMAT_0_1: + dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; + dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; + dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; + dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; + dci_pdu_rel15->dai[0].val = 0; //TODO + // bwp indicator + if (n_ubwp < 4) + dci_pdu_rel15->bwp_indicator.val = bwp_id; + else + dci_pdu_rel15->bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 + // frequency domain assignment + if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) + dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, + pusch_pdu->rb_start, + NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); + else + AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); + // time domain assignment + dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; + // mcs + dci_pdu_rel15->mcs = pusch_pdu->mcs_index; + // tpc command for pusch + dci_pdu_rel15->tpc = 2; //TODO + // SRS resource indicator + if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig != NULL) { + if (*ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook) + dci_pdu_rel15->srs_resource_indicator.val = 0; // taking resource 0 for SRS + else + AssertFatal(1==0,"Non Codebook configuration non supported\n"); + } + // Antenna Ports + dci_pdu_rel15->antenna_ports.val = 0; // TODO for now it is hardcoded, it should depends on cdm group no data and rank + // DMRS sequence initialization + dci_pdu_rel15->dmrs_sequence_initialization.val = pusch_pdu->scid; + break; + default : + AssertFatal(1==0,"Valid UL formats are 0_0 and 0_1 \n"); + } - dci_pdu_rel15->time_domain_assignment.val = 2; // row index used here instead of SLIV; - dci_pdu_rel15->frequency_hopping_flag.val = 0; - dci_pdu_rel15->mcs = 9; - - dci_pdu_rel15->format_indicator = 0; - dci_pdu_rel15->ndi = 1; - dci_pdu_rel15->rv = 0; - dci_pdu_rel15->harq_pid = 0; - dci_pdu_rel15->tpc = 2; - LOG_D(MAC, "[gNB scheduler phytest] ULDCI type 0 payload: PDCCH CCEIndex %d, freq_alloc %d, time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n", pdcch_pdu_rel15->dci_pdu.CceIndex[pdcch_pdu_rel15->numDlDci], dci_pdu_rel15->frequency_domain_assignment.val, @@ -493,10 +542,6 @@ void config_uldci(NR_BWP_Uplink_t *ubwp,nfapi_nr_pusch_pdu_t *pusch_pdu,nfapi_nr dci_pdu_rel15->tpc, dci_pdu_rel15->ndi, dci_pdu_rel15->rv); - - dci_formats[pdcch_pdu_rel15->numDlDci] = NR_UL_DCI_FORMAT_0_0; - rnti_types[pdcch_pdu_rel15->numDlDci] = NR_RNTI_C; - pdcch_pdu_rel15->numDlDci++; } @@ -738,7 +783,7 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; int bwp_id=1; - + int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; int UE_id = 0; NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; AssertFatal(UE_list->active[UE_id] >=0,"Cannot find UE_id %d is not active\n",UE_id); @@ -748,7 +793,9 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, "downlinkBWP_ToAddModList has %d BWP!\n", secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; + int n_ubwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; + NR_PUSCH_Config_t *pusch_Config = ubwp->bwp_Dedicated->pusch_Config->choice.setup; nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; nfapi_nr_ul_dci_request_t *UL_dci_req = &RC.nrmac[Mod_idP]->UL_dci_req[0]; @@ -769,20 +816,28 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, LOG_D(MAC, "Scheduling UE specific PUSCH\n"); //UL_tti_req = &nr_mac->UL_tti_req[CC_id]; - /* - // original configuration - rel15_ul->rnti = 0x1234; - rel15_ul->ulsch_pdu_rel15.start_rb = 30; - rel15_ul->ulsch_pdu_rel15.number_rbs = 50; - rel15_ul->ulsch_pdu_rel15.start_symbol = 2; - rel15_ul->ulsch_pdu_rel15.number_symbols = 12; - rel15_ul->ulsch_pdu_rel15.nb_re_dmrs = 6; - rel15_ul->ulsch_pdu_rel15.length_dmrs = 1; - rel15_ul->ulsch_pdu_rel15.Qm = 2; - rel15_ul->ulsch_pdu_rel15.mcs = 9; - rel15_ul->ulsch_pdu_rel15.rv = 0; - rel15_ul->ulsch_pdu_rel15.n_layers = 1; - */ + + //Resource Allocation in time domain + int startSymbolAndLength=0; + int time_domain_assignment=1; + int StartSymbolIndex,NrOfSymbols,K2,mapping_type; + + AssertFatal(time_domain_assignment<ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count, + "time_domain_assignment %d>=%d\n",time_domain_assignment,ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count); + startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; + SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols); + pusch_pdu->start_symbol_index = StartSymbolIndex; + pusch_pdu->nr_of_symbols = NrOfSymbols; + + mapping_type = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->mappingType; + if (ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2 != NULL) + K2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2; + else { + if (mu<2) K2=1; + else if(mu==2) K2=2; + else K2=3; + } + pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; pusch_pdu->rnti = rnti; pusch_pdu->handle = 0; //not yet used @@ -797,60 +852,123 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, pusch_pdu->mcs_table = 0; //0: notqam256 [TS38.214, table 5.1.3.1-1] - corresponds to nr_target_code_rate_table1 in PHY pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; - pusch_pdu->transform_precoding = 0; - pusch_pdu->data_scrambling_id = 0; //It equals the higher-layer parameter Data-scrambling-Identity if configured and the RNTI equals the C-RNTI, otherwise L2 needs to set it to physical cell id.; + if (pusch_Config->transformPrecoder == NULL) { + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) + pusch_pdu->transform_precoding = 1; + else + pusch_pdu->transform_precoding = 0; + } + else + pusch_pdu->transform_precoding = *pusch_Config->transformPrecoder; + if (pusch_Config->dataScramblingIdentityPUSCH != NULL) + pusch_pdu->data_scrambling_id = *pusch_Config->dataScramblingIdentityPUSCH; + else + pusch_pdu->data_scrambling_id = *scc->physCellId; + pusch_pdu->nrOfLayers = 1; //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] - pusch_pdu->resource_alloc = 1; //type 1 - //pusch_pdu->rb_bitmap;// for ressource alloc type 0 - pusch_pdu->rb_start = 0; - pusch_pdu->rb_size = 50; + if (pusch_Config->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) { + pusch_pdu->resource_alloc = 1; //type 1 + pusch_pdu->rb_start = 0; + pusch_pdu->rb_size = 50; + } + else + AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); + pusch_pdu->vrb_to_prb_mapping = 0; - pusch_pdu->frequency_hopping = 0; + + if (pusch_Config->frequencyHopping==NULL) + pusch_pdu->frequency_hopping = 0; + else + pusch_pdu->frequency_hopping = 1; + //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] - pusch_pdu->uplink_frequency_shift_7p5khz = 0; - //Resource Allocation in time domain - pusch_pdu->start_symbol_index = 2; - pusch_pdu->nr_of_symbols = 12; + //pusch_pdu->uplink_frequency_shift_7p5khz = 0; + // -------------------- // ------- DMRS ------- // -------------------- - uint16_t l_prime_mask = get_l_prime(pusch_pdu->nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); - pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << pusch_pdu->start_symbol_index; - pusch_pdu->dmrs_config_type = 0; // dmrs-type 1 (the one with a single DMRS symbol in the beginning) - pusch_pdu->ul_dmrs_scrambling_id = 0; // If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id - pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] - // Should match what is sent in DCI 0_1, otherwise set to 0 + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig; + if (mapping_type == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA) + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; + else + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + if (NR_DMRS_UplinkConfig->dmrs_Type == NULL) + pusch_pdu->dmrs_config_type = 0; + else + pusch_pdu->dmrs_config_type = 1; + pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] + if (pusch_pdu->transform_precoding) { // transform precoding disabled + long *scramblingid; + if (pusch_pdu->scid == 0) + scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; + else + scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; + if (scramblingid == NULL) + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + else + pusch_pdu->ul_dmrs_scrambling_id = *scramblingid; + } + else { + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + if (NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) + pusch_pdu->pusch_identity = *NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; + else + pusch_pdu->pusch_identity = *scc->physCellId; + } + pusch_dmrs_AdditionalPosition_t additional_pos; + if (NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL) + additional_pos = 2; + else { + if (*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3) + additional_pos = 3; + else + additional_pos = *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition; + } + pusch_maxLength_t pusch_maxLength; + if (NR_DMRS_UplinkConfig->maxLength == NULL) + pusch_maxLength = 1; + else + pusch_maxLength = 2; + uint16_t l_prime_mask = get_l_prime(pusch_pdu->nr_of_symbols, mapping_type, additional_pos, pusch_maxLength); + pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << pusch_pdu->start_symbol_index; + pusch_pdu->num_dmrs_cdm_grps_no_data = 1; - //pusch_pdu->dmrs_ports; // DMRS ports. [TS38.212 7.3.1.1.2] provides description between DCI 0-1 content and DMRS ports - // Bitmap occupying the 11 LSBs with: bit 0: antenna port 1000 bit 11: antenna port 1011, - // and for each bit 0: DMRS port not used 1: DMRS port used + pusch_pdu->dmrs_ports = 1; // -------------------------------------------------------------------------------------------------------------------------------------------- // -------------------- // ------- PTRS ------- // -------------------- - uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig - pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); - pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); - pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; - - if(1<<pusch_pdu->pusch_ptrs.ptrs_time_density >= pusch_pdu->nr_of_symbols) - pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + if (NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { + // TODO to be fixed from RRC config + uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig + uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig + uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig + uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig + uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig + pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); + pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); + pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); + pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + + pusch_pdu->pdu_bit_map &= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + } + else{ +// if(1<<pusch_pdu->pusch_ptrs.ptrs_time_density >= pusch_pdu->nr_of_symbols) + pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + } + // -------------------------------------------------------------------------------------------------------------------------------------------- //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] //Optional Data only included if indicated in pduBitmap + // TODO from harq function as in pdsch pusch_pdu->pusch_data.rv_index = 0; pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = 0; + pusch_pdu->pusch_data.new_data_indicator = 1; uint8_t num_dmrs_symb = 0; @@ -935,9 +1053,10 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, return; } else { - dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; - config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types); - fill_dci_pdu_rel15(secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pusch_pdu->bwp_size,bwp_id); + dci_pdu_rel15_t *dci_pdu_rel15 = calloc(MAX_DCI_CORESET,sizeof(dci_pdu_rel15_t)); + config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15,&dci_pdu_rel15[0],dci_formats,rnti_types,time_domain_assignment,n_ubwp,bwp_id); + fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pusch_pdu->bwp_size,bwp_id); + free(dci_pdu_rel15); } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index fc2a2e18cf86692e6a6c3f1eb4a19d4ea9ff3415..acb239ee39e59ba4ebb98160e55cacf62bd847c3 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}; @@ -734,6 +732,19 @@ void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; switch(format) { + case NR_UL_DCI_FORMAT_0_1: + // format indicator + dci_pdu_rel15->format_indicator = 0; + // carrier indicator + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) + AssertFatal(1==0,"Cross Carrier Scheduling Config currently not supported\n"); + // supplementary uplink + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink != NULL) + AssertFatal(1==0,"Supplementary Uplink currently not supported\n"); + // SRS request + dci_pdu_rel15->srs_request.val = 0; + dci_pdu_rel15->ulsch_indicator = 1; + break; case NR_DL_DCI_FORMAT_1_1: // format indicator dci_pdu_rel15->format_indicator = 1; @@ -782,16 +793,15 @@ void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, // CBGTI and CBGFI if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) AssertFatal(1==0,"CBG transmission currently not supported\n"); - // dmrs sequence initialization - dci_pdu_rel15->dmrs_sequence_initialization = 0; // FIXME no information on what this bit should be in 38.212 break; default : - AssertFatal(1==0,"Prepare dci currently only implemented for 1_1 \n"); + AssertFatal(1==0,"Prepare dci currently only implemented for 1_1 and 0_1 \n"); } } -void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, +void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *secondaryCellGroup, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, @@ -804,11 +814,11 @@ void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++) { uint64_t *dci_pdu = (uint64_t *)pdcch_pdu_rel15->dci_pdu.Payload[d]; - int dci_size = nr_dci_size(secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],rnti_types[d],N_RB,bwp_id); + int dci_size = nr_dci_size(scc,secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],rnti_types[d],N_RB,bwp_id); pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d] = dci_size; AssertFatal(pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d]<=64, "DCI sizes above 64 bits not yet supported"); - if(dci_formats[d]==NR_DL_DCI_FORMAT_1_1) + if(dci_formats[d]==NR_DL_DCI_FORMAT_1_1 || dci_formats[d]==NR_UL_DCI_FORMAT_0_1) prepare_dci(secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],bwp_id); /// Payload generation @@ -1118,6 +1128,110 @@ void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, } break; + case NR_UL_DCI_FORMAT_0_1: + switch(rnti_types[d]) + { + case NR_RNTI_C: + // Indicating a DL DCI format 1bit + pos=1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&0x1)<<(dci_size-pos); + + // Carrier indicator + pos+=dci_pdu_rel15->carrier_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val&((1<<dci_pdu_rel15->carrier_indicator.nbits)-1))<<(dci_size-pos); + + // UL/SUL Indicator + pos+=dci_pdu_rel15->ul_sul_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&((1<<dci_pdu_rel15->ul_sul_indicator.nbits)-1))<<(dci_size-pos); + + // BWP indicator + pos+=dci_pdu_rel15->bwp_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val&((1<<dci_pdu_rel15->bwp_indicator.nbits)-1))<<(dci_size-pos); + + // Frequency domain resource assignment + pos+=dci_pdu_rel15->frequency_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1<<dci_pdu_rel15->frequency_domain_assignment.nbits)-1)) << (dci_size-pos); + + // Time domain resource assignment + pos+=dci_pdu_rel15->time_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val&((1<<dci_pdu_rel15->time_domain_assignment.nbits)-1)) << (dci_size-pos); + + // Frequency hopping + pos+=dci_pdu_rel15->frequency_hopping_flag.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&((1<<dci_pdu_rel15->frequency_hopping_flag.nbits)-1)) << (dci_size-pos); + + // MCS 5bit + pos+=5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); + + // New data indicator 1bit + pos+=1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&0x1)<<(dci_size-pos); + + // Redundancy version 2bit + pos+=2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv&0x3)<<(dci_size-pos); + + // HARQ process number 4bit + pos+=4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos); + + // 1st Downlink assignment index + pos+=dci_pdu_rel15->dai[0].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val&((1<<dci_pdu_rel15->dai[0].nbits)-1))<<(dci_size-pos); + + // 2nd Downlink assignment index + pos+=dci_pdu_rel15->dai[1].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[1].val&((1<<dci_pdu_rel15->dai[1].nbits)-1))<<(dci_size-pos); + + // TPC command for scheduled PUSCH 2bit + pos+=2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc&0x3)<<(dci_size-pos); + + // SRS resource indicator + pos+=dci_pdu_rel15->srs_resource_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_resource_indicator.val&((1<<dci_pdu_rel15->srs_resource_indicator.nbits)-1))<<(dci_size-pos); + + // Precoding info and n. of layers + pos+=dci_pdu_rel15->precoding_information.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->precoding_information.val&((1<<dci_pdu_rel15->precoding_information.nbits)-1))<<(dci_size-pos); + + // Antenna ports + pos+=dci_pdu_rel15->antenna_ports.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val&((1<<dci_pdu_rel15->antenna_ports.nbits)-1))<<(dci_size-pos); + + // SRS request + pos+=dci_pdu_rel15->srs_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val&((1<<dci_pdu_rel15->srs_request.nbits)-1))<<(dci_size-pos); + + // CSI request + pos+=dci_pdu_rel15->csi_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->csi_request.val&((1<<dci_pdu_rel15->csi_request.nbits)-1))<<(dci_size-pos); + + // CBG transmission information + pos+=dci_pdu_rel15->cbgti.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val&((1<<dci_pdu_rel15->cbgti.nbits)-1))<<(dci_size-pos); + + // PTRS DMRS association + pos+=dci_pdu_rel15->ptrs_dmrs_association.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ptrs_dmrs_association.val&((1<<dci_pdu_rel15->ptrs_dmrs_association.nbits)-1))<<(dci_size-pos); + + // Beta offset indicator + pos+=dci_pdu_rel15->beta_offset_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->beta_offset_indicator.val&((1<<dci_pdu_rel15->beta_offset_indicator.nbits)-1))<<(dci_size-pos); + + // DMRS sequence initialization + pos+=dci_pdu_rel15->dmrs_sequence_initialization.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&((1<<dci_pdu_rel15->dmrs_sequence_initialization.nbits)-1))<<(dci_size-pos); + + // UL-SCH indicator + pos+=1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ulsch_indicator&0x1)<<(dci_size-pos); + + break; + } + break; + case NR_DL_DCI_FORMAT_1_1: // Indicating a DL DCI format 1bit pos=1; @@ -1223,7 +1337,7 @@ void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, // DMRS sequence init pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization&0x1)<<(dci_size-pos); + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&0x1)<<(dci_size-pos); } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 78920dd2ea2fb516320205a6eb773534a186ac1e..74c6841a3a370205726d947e569ffb6ad394be77 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -132,7 +132,13 @@ int configure_fapi_dl_pdu(int Mod_id, uint16_t *rbSize, uint16_t *rbStart); -void config_uldci(NR_BWP_Uplink_t *ubwp,nfapi_nr_pusch_pdu_t *pusch_pdu,nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, int *rnti_types); +void config_uldci(NR_BWP_Uplink_t *ubwp, + nfapi_nr_pusch_pdu_t *pusch_pdu, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + dci_pdu_rel15_t *dci_pdu_rel15, + int *dci_formats, int *rnti_types, + int time_domain_assignment, + int n_ubwp, int bwp_id); void configure_fapi_dl_Tx(module_id_t Mod_idP, frame_t frameP, @@ -203,7 +209,8 @@ int nr_configure_pdcch(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, NR_BWP_Downlink_t *bwp); -void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, +void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *secondaryCellGroup, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, @@ -289,6 +296,8 @@ void nr_process_mac_pdu( uint8_t *pduP, uint16_t mac_pdu_len); +int binomial(int n, int k); + /* \brief Function to indicate a received SDU on ULSCH. @param Mod_id Instance ID of gNB diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index 6c2333268734d1fe40ede42e701d2d69d9130d8d..6c6bd30070a3ac55c67f4bd4a2814a5e10854db5 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/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index 583e10da94eedf7dfadc24722335425a68643f9e..c537c536b238fefc93244e38dc73b6e1c022492d 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)); /* @@ -3198,6 +3198,42 @@ uint8_t do_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, ASN_SEQUENCE_ADD(&dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry.criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest.list, &rat); + /* request NR configuration */ + LTE_UECapabilityEnquiry_r8_IEs_t *r8 = &dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry.criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8; + LTE_UECapabilityEnquiry_v8a0_IEs_t r8_a0; + LTE_UECapabilityEnquiry_v1180_IEs_t r11_80; + LTE_UECapabilityEnquiry_v1310_IEs_t r13_10; + LTE_UECapabilityEnquiry_v1430_IEs_t r14_30; + LTE_UECapabilityEnquiry_v1510_IEs_t r15_10; + + memset(&r8_a0, 0, sizeof(r8_a0)); + memset(&r11_80, 0, sizeof(r11_80)); + memset(&r13_10, 0, sizeof(r13_10)); + memset(&r14_30, 0, sizeof(r14_30)); + memset(&r15_10, 0, sizeof(r15_10)); + + r8->nonCriticalExtension = &r8_a0; + r8_a0.nonCriticalExtension = &r11_80; + r11_80.nonCriticalExtension = &r13_10; + r13_10.nonCriticalExtension = &r14_30; + r14_30.nonCriticalExtension = &r15_10; + + /* TODO: no hardcoded values here */ + + OCTET_STRING_t req_freq; + unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 + //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x08, 0x18 }; // bands 7 & nr260 + + //unsigned char req_freq_buf[13] = { 0x00, 0xc0, 0x18, 0x01, 0x01, 0x30, 0x4b, 0x04, 0x0e, 0x08, 0x24, 0x04, 0xd0 }; +// unsigned char req_freq_buf[21] = { +//0x01, 0x60, 0x18, 0x05, 0x80, 0xc0, 0x04, 0x04, 0xc1, 0x2c, 0x10, 0x08, 0x20, 0x30, 0x40, 0xe0, 0x82, 0x40, 0x28, 0x80, 0x9a +// }; + + req_freq.buf = req_freq_buf; + req_freq.size = 5; +// req_freq.size = 21; + + r15_10.requestedFreqBandsNR_MRDC_r15 = &req_freq; if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_LTE_DL_DCCH_Message, (void *)&dl_dcch_msg); } @@ -3276,17 +3312,17 @@ uint8_t do_NR_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, /* TODO: no hardcoded values here */ OCTET_STRING_t req_freq; - //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 + unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x02, 0x68 }; // bands 7 & nr78 //unsigned char req_freq_buf[5] = { 0x00, 0x20, 0x1a, 0x08, 0x18 }; // bands 7 & nr260 //unsigned char req_freq_buf[13] = { 0x00, 0xc0, 0x18, 0x01, 0x01, 0x30, 0x4b, 0x04, 0x0e, 0x08, 0x24, 0x04, 0xd0 }; - unsigned char req_freq_buf[21] = { -0x01, 0x60, 0x18, 0x05, 0x80, 0xc0, 0x04, 0x04, 0xc1, 0x2c, 0x10, 0x08, 0x20, 0x30, 0x40, 0xe0, 0x82, 0x40, 0x28, 0x80, 0x9a - }; +// unsigned char req_freq_buf[21] = { +//0x01, 0x60, 0x18, 0x05, 0x80, 0xc0, 0x04, 0x04, 0xc1, 0x2c, 0x10, 0x08, 0x20, 0x30, 0x40, 0xe0, 0x82, 0x40, 0x28, 0x80, 0x9a +// }; req_freq.buf = req_freq_buf; req_freq.size = 5; - req_freq.size = 21; +// req_freq.size = 21; r15_10.requestedFreqBandsNR_MRDC_r15 = &req_freq; diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.h b/openair2/RRC/LTE/MESSAGES/asn1_msg.h index dda23406100c0d1652ca0d096bff624c441fbf1c..640d18a61f92942a6fcb66c0d52981c2d29e0c75 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 4116f5367eae3e8eed143df266502f6ce9ad69c3..bdf992c76a3c64f8d71acbdb1dea96a7fd349e56 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; + + 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]; + } - 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]; + } - int mnc; + 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; - 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]; - } + 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; + } - LOG_I( RRC, "PLMN MCC %0*d, MNC %0*d, TAC 0x%04x\n", mccdigits, mcc, mncdigits, mnc, + plmn_ind++; + } + } + 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 e366061674279747ddf104af40afc85b8ce79edd..3c02c45bc1edccb68f6a448f0fea01a88c818d36 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 1d44751dcaf6396c61305ccb709660c867f87f3b..16d5065d3763b0390baf2af95f528882dbfa14e5 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; i<NUMBER_OF_UCI_VARS_MAX; i++) { + if(eNB_PHY->uci_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; i<MAX_MOBILES_PER_ENB; i++) { ulsch = eNB_PHY->ulsch[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 27a442ed05c3126aeabbaf986fdd059aacd7fbb6..9f92be366bdb4c82279364755a96c709ac81bfcf 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/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 7b0bb099f76ee93698909d69e50f51dc15c808b8..6ea6f3b3b33181ba9944a27df61963b92797f22c 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -825,7 +825,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; NR_DMRS_UplinkConfig->dmrs_Type = NULL; - NR_DMRS_UplinkConfig->dmrs_AdditionalPosition =NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos0; + NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = calloc(1,sizeof(*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition)); + *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos0; NR_DMRS_UplinkConfig->phaseTrackingRS=NULL; NR_DMRS_UplinkConfig->maxLength=NULL; NR_DMRS_UplinkConfig->transformPrecodingDisabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingDisabled)); @@ -916,7 +917,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco srs_res0->resourceMapping.repetitionFactor=NR_SRS_Resource__resourceMapping__repetitionFactor_n1; srs_res0->freqDomainPosition=0; srs_res0->freqDomainShift=0; - srs_res0->freqHopping.c_SRS = 61; + srs_res0->freqHopping.c_SRS = 0; srs_res0->freqHopping.b_SRS=0; srs_res0->freqHopping.b_hop=0; srs_res0->groupOrSequenceHopping=NR_SRS_Resource__groupOrSequenceHopping_neither; @@ -1095,7 +1096,19 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = 1; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig = NULL; + + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig)); + NR_PUSCH_ServingCellConfig_t *pusch_scc = calloc(1,sizeof(*pusch_scc)); + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->present = NR_SetupRelease_PUSCH_ServingCellConfig_PR_setup; + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup = pusch_scc; + pusch_scc->codeBlockGroupTransmission = NULL; + pusch_scc->rateMatching = NULL; + pusch_scc->xOverhead = NULL; + pusch_scc->ext1=calloc(1,sizeof(*pusch_scc->ext1)); + pusch_scc->ext1->maxMIMO_Layers = calloc(1,sizeof(*pusch_scc->ext1->maxMIMO_Layers)); + *pusch_scc->ext1->maxMIMO_Layers = 1; + pusch_scc->ext1->processingType2Enabled = NULL; + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink=NULL; diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index 6a037b8ee3461f2f53b26ee52d3aa6d8294059e1..bd7727274705b92da83d6c99a00953eaddd4a011 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 c2280342451c3e39a5d93f41b39a95a614848bb1..c70350184706913a3baeb092ae9e8ab698f01cf2 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 c72e7d4130023930cf0aea054828458a4899c622..1d3c280f0e5d18a6485e5bd9f45cb9f3e0bae916 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 1377086e8f47f57eba45b38a32a0c16868e20407..6e94717a6fbcf02525782f11eebf58e31a01cf44 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 b7b435f2d9260cbe514eef093e699bad11f6928b..7b7f20b52ef53d5206787ee027a9114f6a473936 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -44,6 +44,7 @@ #include <common/utils/assertions.h> #include <common/utils/LOG/log.h> #include <common/utils/load_module_shlib.h> +#include <common/utils/telnetsrv/telnetsrv.h> #include <common/config/config_userapi.h> #include "common_lib.h" #include <openair1/PHY/defs_eNB.h> @@ -78,11 +79,25 @@ extern RAN_CONTEXT_t RC; #define RFSIMULATOR_PARAMS_DESC {\ {"serveraddr", "<ip address to connect to>\n", 0, strptr:&(rfsimulator->ip), defstrval:"127.0.0.1", TYPE_STRING, 0 },\ {"serverport", "<port to connect to>\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", "<file path to use when saving IQs>\n", 0, strptr:&(saveF), defstrval:"/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\ - {"modelname", "<channel model name>\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 }\ + {"modelname", "<channel model name>\n", 0, strptr:&(modelname), defstrval:"AWGN", TYPE_STRING, 0 },\ + {"ploss", "<channel path loss in dB>\n", 0, dblptr:&(rfsimulator->chan_pathloss), defdblval:0, TYPE_DOUBLE, 0 },\ + {"forgetfact", "<channel forget factor ((0 to 1)>\n", 0, dblptr:&(rfsimulator->chan_forgetfact), defdblval:0, TYPE_DOUBLE, 0 },\ + {"offset", "<channel offset in samps>\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","<model name>",(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,22 +168,26 @@ 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, - 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); } } @@ -290,6 +314,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; i<FD_SETSIZE; i++) { + buffer_t *b=&t->buf[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; @@ -379,6 +438,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) @@ -480,6 +540,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++) { @@ -490,8 +551,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 ) { @@ -510,7 +573,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); } @@ -640,7 +703,8 @@ 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; a<nbAnt; a++) { if ( ptr->channel_model != NULL ) // apply a channel model rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a], @@ -653,6 +717,7 @@ 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; @@ -734,5 +799,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/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 4715a4e99561fd7af741bcf94133040898a5ce20..435ae6a53de2726651fe949123248ef1ebbd5dd0 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -556,6 +556,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 +727,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 a45ecd22981b3b8d4976d9c9f037414643dafc62..54a9f4a669e7fb8087d1acca604348d46442aa82 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);