Merge remote-tracking branch 'origin/develop' into NR_UL_scheduling
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
|
||||
+284
@@ -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";
|
||||
};
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-61
@@ -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
|
||||
|
||||
+443
-489
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
+97
-193
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Executable
+35
@@ -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
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -27,6 +27,10 @@ cmake_minimum_required (VERSION 3.0)
|
||||
# Base directories, compatible with legacy OAI building #
|
||||
#########################################################
|
||||
set (OPENAIR_DIR $ENV{OPENAIR_DIR})
|
||||
if("${OPENAIR_DIR}" STREQUAL "")
|
||||
string(REGEX REPLACE "/cmake_targets.*$" "" OPENAIR_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
set (NFAPI_DIR ${OPENAIR_DIR}/nfapi/open-nFAPI)
|
||||
set (NFAPI_USER_DIR ${OPENAIR_DIR}/nfapi/oai_integration)
|
||||
set (OPENAIR1_DIR ${OPENAIR_DIR}/openair1)
|
||||
@@ -1252,7 +1256,7 @@ set(SCHED_SRC_NR_UE
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c
|
||||
${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_common.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/fapi_nr_ue_l1.c
|
||||
${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/phy_frame_config_nr_ue.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/harq_nr.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/pucch_uci_ue_nr.c
|
||||
${OPENAIR1_DIR}/SCHED_NR_UE/pucch_power_control_ue_nr.c
|
||||
@@ -1830,6 +1834,7 @@ set (MAC_SRC
|
||||
${MAC_DIR}/eNB_scheduler_fairRR.c
|
||||
${MAC_DIR}/eNB_scheduler_phytest.c
|
||||
${MAC_DIR}/pre_processor.c
|
||||
${MAC_DIR}/slicing/slicing.c
|
||||
${MAC_DIR}/config.c
|
||||
${MAC_DIR}/config_ue.c
|
||||
)
|
||||
@@ -2473,8 +2478,8 @@ add_library(uescope MODULE ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} ${XFORMS_
|
||||
target_link_libraries(enbscope ${XFORMS_LIBRARIES})
|
||||
target_link_libraries(uescope ${XFORMS_LIBRARIES})
|
||||
|
||||
add_library(gnbscope MODULE ${XFORMS_SOURCE_NR})
|
||||
target_link_libraries(gnbscope ${XFORMS_LIBRARIES})
|
||||
add_library(nrscope MODULE ${XFORMS_SOURCE_NR})
|
||||
target_link_libraries(nrscope ${XFORMS_LIBRARIES})
|
||||
|
||||
|
||||
add_library(rfsimulator MODULE
|
||||
@@ -2623,7 +2628,7 @@ add_executable(ocp-enb
|
||||
${CONFIG_SOURCES}
|
||||
${SHLIB_LOADER_SOURCES}
|
||||
)
|
||||
add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer)
|
||||
add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer coding params_libconfig rfsimulator)
|
||||
|
||||
target_link_libraries (ocp-enb
|
||||
-Wl,--start-group
|
||||
@@ -2730,7 +2735,7 @@ add_executable(nr-softmodem
|
||||
${OPENAIR_DIR}/common/utils/system.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
${GTPU_need_ITTI}
|
||||
${XFORMS_SOURCE_NR}
|
||||
${XFORMSINTERFACE_SOURCE}
|
||||
${T_SOURCE}
|
||||
${CONFIG_SOURCES}
|
||||
${SHLIB_LOADER_SOURCES}
|
||||
@@ -2772,7 +2777,7 @@ add_executable(nr-uesoftmodem
|
||||
${OPENAIR_DIR}/common/utils/utils.c
|
||||
${OPENAIR_DIR}/common/utils/system.c
|
||||
${OPENAIR_DIR}/common/utils/nr/nr_common.c
|
||||
${XFORMS_SOURCE_NR}
|
||||
${XFORMSINTERFACE_SOURCE}
|
||||
${T_SOURCE}
|
||||
${UTIL_SRC}
|
||||
${CONFIG_SOURCES}
|
||||
|
||||
+16
-6
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
STATUS 2020/06/26 : information is up to date, but under continuous improvement
|
||||
STATUS 2020/07/30 : under continuous improvement ; updated the configuration files links with CI approved reference files
|
||||
|
||||
|
||||
## Table of Contents ##
|
||||
|
||||
@@ -78,17 +79,17 @@ https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master-documentation/do
|
||||
Each component (EPC, eNB, gNB) has its own configuration file.
|
||||
These config files are passed as arguments of the run command line, using the option -O \<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
|
||||
|
||||
Also base config files can be found here:
|
||||
[enb conf file](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/rh_doc_update_3/doc/testing_gnb_w_cots_ue_resources/enb.conf)
|
||||
[gnb conf file](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/rh_doc_update_3/doc/testing_gnb_w_cots_ue_resources/gnb.conf)
|
||||
|
||||
TO DO : attach base confif files
|
||||
The **REFERENCE** files for eNB and gNB, **used by the CI**, can be found here:
|
||||
[enb conf file](../ci-scripts/conf_files/enb.band7.tm1.fr1.25PRB.usrpb210.conf)
|
||||
[gnb conf file](../ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf)
|
||||
|
||||
These files have to be updated manually to set the IP addresses and frequency.
|
||||
|
||||
|
||||
**ATTENTION** : an **EXTERNAL** clock is used to sync the eNB and gNB,
|
||||
whether the clock is internal or external is defined in the configuration files (!! details needed !!)
|
||||
|
||||
|
||||
1- In the **eNB configuration file** :
|
||||
- look for MME IP address, and update the **ipv4 field** with the IP address of the **EPC** server
|
||||
```
|
||||
@@ -128,7 +129,7 @@ These files have to be updated manually to set the IP addresses and frequency.
|
||||
}
|
||||
);
|
||||
```
|
||||
- look for X2 IP address, and update the **4 fields** with the IP address of the **eNB** server (notice : even if -in principle- S1 MME is not required for gNB setting)
|
||||
- look for X2 IP address, and update the **4 fields** with the IP address of the **eNB** server / **gNB** server as below (notice : even if -in principle- S1 MME is not required for gNB setting)
|
||||
```
|
||||
|
||||
///X2
|
||||
@@ -146,11 +147,11 @@ These files have to be updated manually to set the IP addresses and frequency.
|
||||
{
|
||||
|
||||
GNB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_S1_MME = "**YOUR_ENB_IP_ADDR**";
|
||||
GNB_IPV4_ADDRESS_FOR_S1_MME = "**YOUR_GNB_IP_ADDR**";
|
||||
GNB_INTERFACE_NAME_FOR_S1U = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_S1U = "**YOUR_ENB_IP_ADDR**";
|
||||
GNB_IPV4_ADDRESS_FOR_S1U = "**YOUR_GNB_IP_ADDR**";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
GNB_IPV4_ADDRESS_FOR_X2C = "**YOUR_ENB_IP_ADDR**";
|
||||
GNB_IPV4_ADDRESS_FOR_X2C = "**YOUR_GNB_IP_ADDR**";
|
||||
GNB_PORT_FOR_X2C = 36422; # Spec 36422
|
||||
};
|
||||
|
||||
@@ -215,26 +216,20 @@ Execute:
|
||||
|
||||
```
|
||||
|
||||
For example:
|
||||
```
|
||||
~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf | tee mylogfile.log
|
||||
```
|
||||
|
||||
|
||||
|
||||
- **gNB** (on the gNB host)
|
||||
|
||||
|
||||
Execute:
|
||||
```
|
||||
~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O **YOUR_GNB_CONF_FILE** | tee **YOUR_LOG_FILE**
|
||||
~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O **YOUR_GNB_CONF_FILE** -E | tee **YOUR_LOG_FILE**
|
||||
|
||||
```
|
||||
|
||||
For example:
|
||||
```
|
||||
~/openairinterface5g/cmake_targets/ran_build/build$ sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf | tee mylogfile.log
|
||||
```
|
||||
**ATTENTION** : for the gNB execution,
|
||||
The -E option is required to enable the tri-quarter sampling rate when using a B2xx serie USRP
|
||||
The -E opton is not needed when using a a N300 USRP
|
||||
|
||||
|
||||
|
||||
## Test Case
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -1123,9 +1123,6 @@ int restart_L1L2(module_id_t enb_id) {
|
||||
sync_var = -1;
|
||||
pthread_mutex_unlock(&sync_mutex);
|
||||
RC.ru_mask |= (1 << ru->idx);
|
||||
/* copy the changed frame parameters to the RU */
|
||||
/* TODO this should be done for all RUs associated to this eNB */
|
||||
memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS));
|
||||
/* reset the list of connected UEs in the MAC, since in this process with
|
||||
* loose all UEs (have to reconnect) */
|
||||
init_UE_info(&RC.mac[enb_id]->UE_info);
|
||||
@@ -1167,6 +1164,7 @@ int main ( int argc, char **argv ) {
|
||||
T_Config_Init();
|
||||
#endif
|
||||
configure_linux();
|
||||
set_softmodem_sighandler();
|
||||
cpuf=get_cpu_freq_GHz();
|
||||
set_taus_seed (0);
|
||||
|
||||
@@ -1347,7 +1345,7 @@ int main ( int argc, char **argv ) {
|
||||
// end of CI modifications
|
||||
//getchar();
|
||||
if(IS_SOFTMODEM_DOFORMS)
|
||||
load_softscope("enb");
|
||||
load_softscope("enb", NULL);
|
||||
|
||||
itti_wait_tasks_end();
|
||||
oai_exit=1;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -723,9 +726,6 @@ int restart_L1L2(module_id_t gnb_id) {
|
||||
|
||||
|
||||
RC.ru_mask |= (1 << ru->idx);
|
||||
/* copy the changed frame parameters to the RU */
|
||||
/* TODO this should be done for all RUs associated to this gNB */
|
||||
memcpy(&ru->nr_frame_parms, &RC.gNB[gnb_id]->frame_parms, sizeof(NR_DL_FRAME_PARMS));
|
||||
set_function_spec_param(RC.ru[gnb_id]);
|
||||
LOG_I(GNB_APP, "attempting to create ITTI tasks\n");
|
||||
// No more rrc thread, as many race conditions are hidden behind
|
||||
@@ -817,7 +817,6 @@ int main( int argc, char **argv )
|
||||
configure_linux();
|
||||
printf("Reading in command-line options\n");
|
||||
get_options ();
|
||||
get_common_options(SOFTMODEM_GNB_BIT );
|
||||
|
||||
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
|
||||
fprintf(stderr,"Getting configuration failed\n");
|
||||
@@ -959,14 +958,14 @@ if(!IS_SOFTMODEM_NOS1)
|
||||
printf("RC.nb_RU:%d\n", RC.nb_RU);
|
||||
// once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
|
||||
printf("ALL RUs ready - init gNBs\n");
|
||||
|
||||
if (do_forms==1) {
|
||||
if(IS_SOFTMODEM_DOFORMS) {
|
||||
|
||||
scopeParms_t p;
|
||||
p.argc=&argc;
|
||||
p.argv=argv;
|
||||
p.gNB=RC.gNB[0];
|
||||
p.ru=RC.ru[0];
|
||||
gNBinitScope(&p);
|
||||
load_softscope("nr",&p);
|
||||
}
|
||||
|
||||
if (nfapi_mode != 1 && nfapi_mode != 2) {
|
||||
|
||||
@@ -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}, \
|
||||
}
|
||||
|
||||
+1
-9
@@ -35,9 +35,7 @@
|
||||
#include "NR_MAC_UE/mac_proto.h"
|
||||
#include "RRC/NR_UE/rrc_proto.h"
|
||||
|
||||
//#ifndef NO_RAT_NR
|
||||
#include "SCHED_NR/phy_frame_config_nr.h"
|
||||
//#endif
|
||||
#include "SCHED_NR_UE/phy_frame_config_nr.h"
|
||||
#include "SCHED_NR_UE/defs.h"
|
||||
|
||||
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
||||
@@ -577,12 +575,6 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
|
||||
int computeSamplesShift(PHY_VARS_NR_UE *UE) {
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
LOG_D(PHY,"SET rx_offset %d \n",UE->rx_offset);
|
||||
//UE->rx_offset_diff=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// compute TO compensation that should be applied for this frame
|
||||
if ( UE->rx_offset < UE->frame_parms.samples_per_frame/2 &&
|
||||
UE->rx_offset > 0 ) {
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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}, \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -364,7 +364,7 @@ typedef struct
|
||||
//table 3-22
|
||||
typedef struct
|
||||
{
|
||||
nfapi_uint8_tlv_t phy_cell_id;//Physical Cell ID, 𝑁_{𝐼𝐷}^{𝑐𝑒𝑙𝑙} [38.211, sec 7.4.2.1] Value: 0 ->1007
|
||||
nfapi_uint16_tlv_t phy_cell_id;//Physical Cell ID, 𝑁_{𝐼𝐷}^{𝑐𝑒𝑙𝑙} [38.211, sec 7.4.2.1] Value: 0 ->1007
|
||||
nfapi_uint8_tlv_t frame_duplex_type;//Frame duplex type Value: 0 = FDD 1 = TDD
|
||||
|
||||
} nfapi_nr_cell_config_t;
|
||||
|
||||
@@ -186,7 +186,6 @@ void phy_free_RU(RU_t *ru) {
|
||||
int i,j,p;
|
||||
RU_CALIBRATION *calibration = &ru->calibration;
|
||||
LOG_I(PHY, "Feeing RU signal buffers (if_south %s) nb_tx %d\n", ru_if_types[ru->if_south], ru->nb_tx);
|
||||
free_and_zero(ru->frame_parms);
|
||||
|
||||
if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so free memory for time-domain signals
|
||||
for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdata[i]);
|
||||
|
||||
@@ -121,9 +121,9 @@ int nr_phy_init_RU(RU_t *ru) {
|
||||
LOG_E(PHY,"[INIT] %s() RC.nb_nr_L1_inst:%d \n", __FUNCTION__, RC.nb_nr_L1_inst);
|
||||
|
||||
int beam_count = 0;
|
||||
if (ru->nb_log_antennas>1) {
|
||||
if (ru->nb_tx>1) {//Enable beamforming when nb_tx > 1
|
||||
for (p=0;p<ru->nb_log_antennas;p++) {
|
||||
if ((fp->L_ssb >> p) & 0x01)
|
||||
if ((fp->L_ssb >> (63-p)) & 0x01)//64 bit-map with the MSB @2⁶³ corresponds to SSB ssb_index 0
|
||||
beam_count++;
|
||||
}
|
||||
AssertFatal(ru->nb_bfw==(beam_count*ru->nb_tx),"Number of beam weights from config file is %d while the expected number is %d",ru->nb_bfw,(beam_count*ru->nb_tx));
|
||||
@@ -131,7 +131,7 @@ int nr_phy_init_RU(RU_t *ru) {
|
||||
int l_ind = 0;
|
||||
for (i=0; i<RC.nb_nr_L1_inst; i++) {
|
||||
for (p=0;p<ru->nb_log_antennas;p++) {
|
||||
if ((fp->L_ssb >> p) & 0x01) {
|
||||
if ((fp->L_ssb >> (63-p)) & 0x01) {
|
||||
ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*));
|
||||
for (j=0; j<ru->nb_tx; j++) {
|
||||
ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t));
|
||||
|
||||
@@ -308,7 +308,7 @@ int nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg,
|
||||
int num_tx_ant = (cfg == NULL) ? fp->Lmax : cfg->carrier_config.num_tx_ant.value;
|
||||
|
||||
for (int p=0; p<num_tx_ant; p++)
|
||||
fp->N_ssb += ((fp->L_ssb >> p) & 0x01);
|
||||
fp->N_ssb += ((fp->L_ssb >> (63-p)) & 0x01);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -389,7 +389,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
|
||||
|
||||
fp->N_ssb = 0;
|
||||
for (int p=0; p<fp->Lmax; p++)
|
||||
fp->N_ssb += ((fp->L_ssb >> p) & 0x01);
|
||||
fp->N_ssb += ((fp->L_ssb >> (63-p)) & 0x01);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -155,7 +155,7 @@ int nr_beam_precoding(int32_t **txdataF,
|
||||
memset(&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size],0,sizeof(int32_t)*(frame_parms->ofdm_symbol_size));
|
||||
|
||||
for (p=0; p<nb_antenna_ports; p++) {
|
||||
if ((frame_parms->L_ssb >> p) & 0x01) {
|
||||
if ((frame_parms->L_ssb >> (63-p)) & 0x01) {
|
||||
multadd_cpx_vector((int16_t*)&txdataF[p][symbol*frame_parms->ofdm_symbol_size],
|
||||
(int16_t*)beam_weights[p][aa],
|
||||
(int16_t*)&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size],
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
extern uint16_t prach_root_sequence_map_0_3[838];
|
||||
extern uint16_t prach_root_sequence_map_abc[138];
|
||||
extern uint16_t nr_du[838];
|
||||
extern int16_t nr_ru[2*839];
|
||||
extern const char *prachfmt[9];
|
||||
|
||||
void init_prach_list(PHY_VARS_gNB *gNB) {
|
||||
@@ -540,7 +539,7 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
|
||||
uint16_t rootSequenceIndex;
|
||||
int numrootSequenceIndex;
|
||||
uint8_t restricted_set;
|
||||
uint8_t n_ra_prb;
|
||||
uint8_t n_ra_prb=0xFF;
|
||||
int16_t *prachF=NULL;
|
||||
int nb_rx;
|
||||
|
||||
|
||||
@@ -353,4 +353,5 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu,
|
||||
nfapi_nr_pucch_pdu_t* pucch_pdu);
|
||||
|
||||
|
||||
#endif /*__NR_TRANSPORT__H__*/
|
||||
|
||||
@@ -266,8 +266,14 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
double Coderate;// = 0.0;
|
||||
|
||||
uint8_t dmrs_Type = harq_process->dmrsConfigType;
|
||||
AssertFatal(dmrs_Type == 1 || dmrs_Type == 2,"Illegal dmrs_type %d\n",dmrs_Type);
|
||||
uint8_t nb_re_dmrs = (dmrs_Type==1)?6:4; // should be changed based on MAC parameters
|
||||
AssertFatal(dmrs_Type == 0 || dmrs_Type == 1, "Illegal dmrs_type %d\n", dmrs_Type);
|
||||
uint8_t nb_re_dmrs;
|
||||
if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) {
|
||||
nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups;
|
||||
}
|
||||
else {
|
||||
nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups;
|
||||
}
|
||||
uint16_t dmrs_length = get_num_dmrs(harq_process->dlDmrsSymbPos);
|
||||
AssertFatal(dmrs_length == 1 || dmrs_length == 2,"Illegal dmrs_length %d\n",dmrs_length);
|
||||
|
||||
@@ -805,7 +811,12 @@ uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
|
||||
//nfapi_nr_config_request_t *cfg = &phy_vars_ue->nrUE_config;
|
||||
//uint8_t dmrs_type = cfg->pdsch_config.dmrs_type.value;
|
||||
|
||||
uint8_t nb_re_dmrs = 12;//(dmrs_type==1)?6:4;
|
||||
uint8_t nb_re_dmrs;
|
||||
if (dmrs_Type == NFAPI_NR_DMRS_TYPE1)
|
||||
nb_re_dmrs = 6*harq_process->n_dmrs_cdm_groups;
|
||||
else
|
||||
nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups;
|
||||
|
||||
uint16_t length_dmrs = get_num_dmrs(dl_config_pdu->dlDmrsSymbPos);
|
||||
|
||||
uint32_t i,j;
|
||||
|
||||
@@ -134,7 +134,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
int avgs = 0;// rb;
|
||||
NR_DL_UE_HARQ_t *dlsch0_harq, *dlsch1_harq = NULL;
|
||||
|
||||
uint8_t beamforming_mode;
|
||||
uint8_t beamforming_mode = 0;
|
||||
|
||||
int32_t **rxdataF_comp_ptr;
|
||||
int32_t **dl_ch_mag_ptr;
|
||||
@@ -162,24 +162,34 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
pdsch_vars = ue->pdsch_vars_SI;
|
||||
dlsch = &ue->dlsch_SI[eNB_id];
|
||||
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
|
||||
beamforming_mode = 0;
|
||||
|
||||
break;
|
||||
|
||||
case RA_PDSCH:
|
||||
pdsch_vars = ue->pdsch_vars_ra;
|
||||
dlsch = &ue->dlsch_ra[eNB_id];
|
||||
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
|
||||
beamforming_mode = 0;
|
||||
|
||||
// WIP TBR Hotfix
|
||||
memcpy((void*)&pdsch_vars[eNB_id]->dl_ch_estimates[0][ue->frame_parms.ofdm_symbol_size*2], (void*)&ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]][0]->dl_ch_estimates[0][ue->frame_parms.ofdm_symbol_size*2], ue->frame_parms.ofdm_symbol_size*sizeof(int32_t));
|
||||
|
||||
break;
|
||||
|
||||
case PDSCH:
|
||||
pdsch_vars = ue->pdsch_vars[ue->current_thread_id[nr_tti_rx]];
|
||||
dlsch = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id];
|
||||
beamforming_mode = ue->transmission_mode[eNB_id] < 7 ? 0 :ue->transmission_mode[eNB_id];
|
||||
|
||||
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
|
||||
dlsch1_harq = dlsch[1]->harq_processes[harq_pid];
|
||||
beamforming_mode = ue->transmission_mode[eNB_id] < 7 ? 0 :ue->transmission_mode[eNB_id];
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(PHY, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dlsch1_harq){
|
||||
|
||||
//printf("status TB0 = %d, status TB1 = %d \n", dlsch[0]->harq_processes[harq_pid]->status, dlsch[1]->harq_processes[harq_pid]->status);
|
||||
LOG_D(PHY,"AbsSubframe %d.%d / Sym %d harq_pid %d, harq status %d.%d \n", frame, nr_tti_rx, symbol, harq_pid, dlsch0_harq->status, dlsch1_harq->status);
|
||||
@@ -191,47 +201,51 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
dlsch1_harq = dlsch[codeword_TB1]->harq_processes[harq_pid];
|
||||
|
||||
#ifdef DEBUG_HARQ
|
||||
printf("[DEMOD] I am assuming both TBs are active\n");
|
||||
printf("[DEMOD] I am assuming both TBs are active, in cw0 %d and cw1 %d \n", codeword_TB0, codeword_TB1);
|
||||
#endif
|
||||
|
||||
} else if ((dlsch0_harq->status == ACTIVE) && (dlsch1_harq->status != ACTIVE) ) {
|
||||
codeword_TB0 = dlsch0_harq->codeword;
|
||||
codeword_TB1 = -1;
|
||||
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
|
||||
dlsch0_harq = dlsch[codeword_TB0]->harq_processes[harq_pid];
|
||||
dlsch1_harq = NULL;
|
||||
|
||||
#ifdef DEBUG_HARQ
|
||||
printf("[DEMOD] I am assuming only TB0 is active\n");
|
||||
printf("[DEMOD] I am assuming only TB0 is active, in cw %d \n", codeword_TB0);
|
||||
#endif
|
||||
|
||||
} else if ((dlsch0_harq->status != ACTIVE) && (dlsch1_harq->status == ACTIVE)){
|
||||
codeword_TB0 = -1;
|
||||
codeword_TB1 = dlsch1_harq->codeword;
|
||||
dlsch0_harq = NULL;
|
||||
dlsch1_harq = dlsch[1]->harq_processes[codeword_TB1];
|
||||
dlsch1_harq = dlsch[codeword_TB1]->harq_processes[harq_pid];
|
||||
|
||||
#ifdef DEBUG_HARQ
|
||||
printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", dlsch1_harq->codeword);
|
||||
printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", codeword_TB1);
|
||||
#endif
|
||||
|
||||
AssertFatal(1 == 0, "[UE][FATAL] DLSCH: TB0 not active and TB1 active case is not supported\n");
|
||||
LOG_E(PHY, "[UE][FATAL] DLSCH: TB0 not active and TB1 active case is not supported\n");
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n", nr_tti_rx);
|
||||
return(-1);
|
||||
}
|
||||
} else if (dlsch0_harq) {
|
||||
if (dlsch0_harq->status == ACTIVE)
|
||||
codeword_TB0 = dlsch0_harq->codeword;
|
||||
dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1 == 0, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type);
|
||||
return(-1);
|
||||
break;
|
||||
|
||||
#ifdef DEBUG_HARQ
|
||||
printf("[DEMOD] I am assuming only TB0 is active\n");
|
||||
#endif
|
||||
} else {
|
||||
LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n", nr_tti_rx);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (dlsch0_harq == NULL)
|
||||
AssertFatal(1 == 0, "Done\n");
|
||||
if (dlsch0_harq == NULL) {
|
||||
LOG_E(PHY, "Done\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dlsch0_harq->Qm = nr_get_Qm_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table);
|
||||
dlsch0_harq->R = nr_get_code_rate_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table);
|
||||
@@ -2377,7 +2391,7 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF,
|
||||
|
||||
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
|
||||
|
||||
k = frame_parms->first_carrier_offset + 12*start_rb;
|
||||
k = frame_parms->first_carrier_offset + NR_NB_SC_PER_RB*start_rb;
|
||||
|
||||
if (high_speed_flag == 1)
|
||||
dl_ch0 = &dl_ch_estimates[aarx][(2*(frame_parms->ofdm_symbol_size))];
|
||||
|
||||
@@ -44,18 +44,8 @@
|
||||
|
||||
//#define NR_PRACH_DEBUG 1
|
||||
|
||||
extern uint16_t NCS_unrestricted_delta_f_RA_125[16];
|
||||
extern uint16_t NCS_restricted_TypeA_delta_f_RA_125[15];
|
||||
extern uint16_t NCS_restricted_TypeB_delta_f_RA_125[13];
|
||||
extern uint16_t NCS_unrestricted_delta_f_RA_5[16];
|
||||
extern uint16_t NCS_restricted_TypeA_delta_f_RA_5[16];
|
||||
extern uint16_t NCS_restricted_TypeB_delta_f_RA_5[14];
|
||||
extern uint16_t NCS_unrestricted_delta_f_RA_15[16];
|
||||
extern uint16_t prach_root_sequence_map_0_3[838];
|
||||
extern uint16_t prach_root_sequence_map_abc[138];
|
||||
extern int64_t table_6_3_3_2_2_prachConfig_Index [256][9];
|
||||
extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9];
|
||||
extern int64_t table_6_3_3_2_4_prachConfig_Index [256][10];
|
||||
extern uint16_t nr_du[838];
|
||||
extern int16_t nr_ru[2*839];
|
||||
extern const char *prachfmt[9];
|
||||
@@ -118,7 +108,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
else
|
||||
samp_count = (slot%(fp->slots_per_subframe/2)) ? fp->samples_per_slotN0 : fp->samples_per_slot0;
|
||||
|
||||
#if defined (OAI_USRP)
|
||||
#ifdef OAI_USRP
|
||||
prach_start = (ue->rx_offset + slot*samp_count - ue->hw_timing_advance - ue->N_TA_offset);
|
||||
#else //normal case (simulation)
|
||||
prach_start = slot*samp_count - ue->N_TA_offset;
|
||||
@@ -208,14 +198,17 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
// now generate PRACH signal
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
if (NCS>0)
|
||||
LOG_I(PHY, "PRACH [UE %d] generate PRACH for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d\n", Mod_id,
|
||||
rootSequenceIndex,
|
||||
preamble_index,
|
||||
prach_sequence_length == 0 ? prachfmt03[prach_fmt_id] : prachfmt[prach_fmt_id],
|
||||
LOG_I(PHY, "PRACH [UE %d] generate PRACH in slot %d for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d msg1 frequency start %d\n",
|
||||
Mod_id,
|
||||
slot,
|
||||
rootSequenceIndex,
|
||||
preamble_index,
|
||||
prach_sequence_length == 0 ? prachfmt03[prach_fmt_id] : prachfmt[prach_fmt_id],
|
||||
NCS,
|
||||
N_ZC,
|
||||
preamble_offset,
|
||||
preamble_shift);
|
||||
preamble_shift,
|
||||
n_ra_prb);
|
||||
#endif
|
||||
|
||||
// nsymb = (frame_parms->Ncp==0) ? 14:12;
|
||||
@@ -383,8 +376,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
|
||||
} else {
|
||||
|
||||
//LOG_D(PHY, "PRACH [UE %d] in slot %d, format %d, msg1 frequency start %d startSymbol %d \n", Mod_id, slot, prachfmt[prach_fmt_id], n_ra_prb, prachStartSymbol);
|
||||
|
||||
switch (prach_fmt_id) {
|
||||
case 0: //A1
|
||||
Ncp = 288/(1<<mu);
|
||||
@@ -419,7 +410,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(PHY, "PRACH [UE %d] Ncp %d, dftlen %d \n", Mod_id, Ncp, dftlen);
|
||||
#ifdef NR_PRACH_DEBUG
|
||||
LOG_D(PHY, "PRACH [UE %d] Ncp %d, dftlen %d \n", Mod_id, Ncp, dftlen);
|
||||
#endif
|
||||
|
||||
if (fp->N_RB_UL <= 100)
|
||||
AssertFatal(1==0,"N_RB_UL %d not supported for NR PRACH yet\n",fp->N_RB_UL);
|
||||
@@ -844,7 +837,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
|
||||
//}
|
||||
//printf(" \n");
|
||||
|
||||
#if defined(PRACH_WRITE_OUTPUT_DEBUG)
|
||||
#ifdef PRACH_WRITE_OUTPUT_DEBUG
|
||||
LOG_M("prach_tx0.m", "prachtx0", prach+(Ncp<<1), prach_len-Ncp, 1, 1);
|
||||
LOG_M("Prach_txsig.m","txs",(int16_t*)(&ue->common_vars.txdata[0][prach_start]), 2*(prach_start+prach_len), 1, 1)
|
||||
#endif
|
||||
|
||||
@@ -292,6 +292,8 @@ typedef struct {
|
||||
uint16_t dlDmrsSymbPos;
|
||||
/// DMRS Configuration Type
|
||||
uint8_t dmrsConfigType;
|
||||
// Number of DMRS CDM groups with no data
|
||||
uint8_t n_dmrs_cdm_groups;
|
||||
/// Starting Symbol number
|
||||
uint16_t start_symbol;
|
||||
/// Current subband PMI allocation
|
||||
|
||||
@@ -100,7 +100,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
|
||||
LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot);
|
||||
|
||||
uint32_t available_bits, TBS;
|
||||
uint32_t available_bits;
|
||||
uint8_t mod_order, cwd_index, num_of_codewords, l;
|
||||
uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5];
|
||||
uint32_t ***pusch_dmrs;
|
||||
@@ -113,7 +113,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
int ap, start_symbol, Nid_cell, i;
|
||||
int sample_offsetF, N_RE_prime, N_PRB_oh;
|
||||
uint16_t ul_dmrs_symb_pos;
|
||||
uint8_t data_existing =0;
|
||||
uint8_t L_ptrs, K_ptrs; // PTRS parameters
|
||||
uint16_t beta_ptrs; // PTRS parameter related to power control
|
||||
|
||||
@@ -121,7 +120,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
NR_UL_UE_HARQ_t *harq_process_ul_ue=NULL;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms;
|
||||
NR_UE_PUSCH *pusch_ue = UE->pusch_vars[thread_id][gNB_id];
|
||||
uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES];
|
||||
// ptrs_UplinkConfig_t *ptrs_Uplink_Config = &UE->pusch_config.dmrs_UplinkConfig.ptrs_UplinkConfig;
|
||||
|
||||
num_of_codewords = 1; // tmp assumption
|
||||
@@ -171,54 +169,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
0,
|
||||
harq_process_ul_ue->pusch_pdu.nrOfLayers);
|
||||
|
||||
uint8_t access_mode = SCHEDULED_ACCESS;
|
||||
|
||||
//-----------------------------------------------------//
|
||||
// to be removed later when MAC is ready
|
||||
|
||||
if (harq_process_ul_ue != NULL){
|
||||
TBS = harq_process_ul_ue->pusch_pdu.pusch_data.tb_size;
|
||||
data_existing = 0;
|
||||
|
||||
if (IS_SOFTMODEM_NOS1){
|
||||
data_existing = nr_ue_get_sdu(UE->Mod_id, UE->CC_id, frame,
|
||||
slot, 0, ulsch_input_buffer, TBS/8, &access_mode);
|
||||
//IP traffic to be transmitted
|
||||
if(data_existing){
|
||||
//harq_process_ul_ue->a = (unsigned char*)calloc(harq_process_ul_ue->TBS/8, sizeof(unsigned char));
|
||||
memcpy(harq_process_ul_ue->a, ulsch_input_buffer, TBS/8);
|
||||
}
|
||||
}
|
||||
//Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
|
||||
if (!IS_SOFTMODEM_NOS1 || !data_existing) {
|
||||
//Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
|
||||
//and block this traffic from being forwarded to the upper layers at the gNB
|
||||
LOG_D(PHY, "Random data to be tranmsitted: \n");
|
||||
|
||||
//Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2)
|
||||
//in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should
|
||||
//have a valid LCID (nr_process_mac_pdu function)
|
||||
harq_process_ul_ue->a[0] = 0x31;
|
||||
|
||||
for (i = 1; i < TBS / 8; i++) {
|
||||
harq_process_ul_ue->a[i] = (unsigned char) rand();
|
||||
//printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_MAC_PDU
|
||||
LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", TBS/8);
|
||||
for (i = 0; i < TBS / 8; i++) {
|
||||
printf("%02x",harq_process_ul_ue->a[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
} else {
|
||||
LOG_E(PHY, "[phy_procedures_nrUE_TX] harq_process_ul_ue is NULL !!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------//
|
||||
|
||||
/////////////////////////ULSCH coding/////////////////////////
|
||||
///////////
|
||||
|
||||
@@ -471,7 +421,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
|
||||
///////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LOG_D(PHY, "Is data existing ?: %d \n", data_existing);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -963,7 +963,7 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue,
|
||||
uint64_t b[16]; // limit to 1024-bit encoded length
|
||||
// M_bit is the number of bits of block b (payload after encoding)
|
||||
uint16_t M_bit;
|
||||
nr_uci_encoding(payload,nr_bit,pucch_format2_nr,0,nrofSymbols,nrofPRB,1,0,0,(void*)b,&M_bit);
|
||||
nr_uci_encoding(payload,nr_bit,pucch_format2_nr,0,nrofSymbols,nrofPRB,1,0,0,&b[0],&M_bit);
|
||||
/*
|
||||
* Implementing TS 38.211
|
||||
* Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2)
|
||||
@@ -985,7 +985,7 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue,
|
||||
/*
|
||||
* Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2
|
||||
*/
|
||||
nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,b,btilde);
|
||||
nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,&b[0],btilde);
|
||||
/*
|
||||
* Implementing TS 38.211 Subclause 6.3.2.5.2 modulation format 2
|
||||
* btilde shall be modulated as described in subclause 5.1 using QPSK
|
||||
@@ -1154,7 +1154,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue,
|
||||
//nrofPRB = 2; // only for test purposes
|
||||
if (fmt == pucch_format4_nr) nrofPRB = 1;
|
||||
|
||||
nr_uci_encoding(payload,nr_bit,fmt,is_pi_over_2_bpsk_enabled,nrofSymbols,nrofPRB,n_SF_PUCCH_s,intraSlotFrequencyHopping,add_dmrs,(void*)b,&M_bit);
|
||||
nr_uci_encoding(payload,nr_bit,fmt,is_pi_over_2_bpsk_enabled,nrofSymbols,nrofPRB,n_SF_PUCCH_s,intraSlotFrequencyHopping,add_dmrs,&b[0],&M_bit);
|
||||
/*
|
||||
* Implementing TS 38.211
|
||||
* Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4)
|
||||
@@ -1176,7 +1176,7 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue,
|
||||
/*
|
||||
* Implementing TS 38.211 Subclause 6.3.2.6.1 scrambling formats 3 and 4
|
||||
*/
|
||||
nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,b,btilde);
|
||||
nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,&b[0],btilde);
|
||||
/*
|
||||
* Implementing TS 38.211 Subclause 6.3.2.6.2 modulation formats 3 and 4
|
||||
*
|
||||
|
||||
@@ -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
|
||||
@@ -400,7 +401,8 @@ static void *scope_thread_gNB(void *arg) {
|
||||
// FILE *gNB_stats = fopen("gNB_stats.txt", "w");
|
||||
//#endif
|
||||
size_t stksize=0;
|
||||
pthread_attr_t atr= {0};
|
||||
pthread_attr_t atr;
|
||||
pthread_attr_init(&atr);
|
||||
pthread_attr_getstacksize(&atr, &stksize);
|
||||
pthread_attr_setstacksize(&atr,32*1024*1024 );
|
||||
sleep(3); // no clean interthread barriers
|
||||
@@ -768,6 +770,15 @@ void nrUEinitScope(PHY_VARS_NR_UE *ue) {
|
||||
threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
|
||||
|
||||
void nrscope_autoinit(void *dataptr) {
|
||||
AssertFatal( (IS_SOFTMODEM_GNB_BIT||IS_SOFTMODEM_5GUE_BIT),"Scope cannot find NRUE or GNB context");
|
||||
|
||||
if (IS_SOFTMODEM_GNB_BIT)
|
||||
gNBinitScope(dataptr);
|
||||
else
|
||||
nrUEinitScope(dataptr);
|
||||
}
|
||||
// Kept to put back the functionality soon
|
||||
#if 0
|
||||
//FD_stats_form *form_stats=NULL,*form_stats_l2=NULL;
|
||||
@@ -795,6 +806,8 @@ static void reset_stats_gNB(FL_OBJECT *button,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static FD_stats_form *create_form_stats_form(int ID) {
|
||||
FL_OBJECT *obj;
|
||||
FD_stats_form *fdui = calloc(( sizeof *fdui ),1);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -31,5 +31,5 @@
|
||||
*/
|
||||
|
||||
|
||||
int load_softscope(char *exectype);
|
||||
int load_softscope(char *exectype, void *initarg);
|
||||
int end_forms(void) ;
|
||||
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -159,6 +159,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
|
||||
gNB->dlsch[i][0]->rnti=0;
|
||||
gNB->dlsch[i][0]->harq_mask=0;
|
||||
}
|
||||
|
||||
gNB->pbch_configured=0;
|
||||
|
||||
for (int i=0;i<number_dl_pdu;i++) {
|
||||
|
||||
@@ -29,11 +29,9 @@
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#include "SCHED_NR_UE/defs.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "SCHED_NR_UE/phy_frame_config_nr.h"
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/impl_defs_top.h"
|
||||
#include "SCHED_NR/phy_frame_config_nr.h"
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
@@ -369,73 +367,6 @@ int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti)
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : nr_ue_slot_select
|
||||
*
|
||||
* DESCRIPTION : function for the UE equivalent to nr_slot_select
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti) {
|
||||
/* for FFD all slot can be considered as an uplink */
|
||||
int mu = cfg->ssb_config.scs_common, check_slot = 0;
|
||||
|
||||
if (cfg->cell_config.frame_duplex_type == FDD) {
|
||||
return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT);
|
||||
}
|
||||
|
||||
if (nr_frame%2 == 0) {
|
||||
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) {
|
||||
check_slot++;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
|
||||
return (NR_UPLINK_SLOT);
|
||||
}
|
||||
|
||||
check_slot = 0;
|
||||
|
||||
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) {
|
||||
check_slot++;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
|
||||
return (NR_DOWNLINK_SLOT);
|
||||
} else {
|
||||
return (NR_MIXED_SLOT);
|
||||
}
|
||||
} else {
|
||||
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[((1<<mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) + nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) {
|
||||
check_slot++;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
|
||||
return (NR_UPLINK_SLOT);
|
||||
}
|
||||
|
||||
check_slot = 0;
|
||||
|
||||
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[((1<<mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) + nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) {
|
||||
check_slot++;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
|
||||
return (NR_DOWNLINK_SLOT);
|
||||
} else {
|
||||
return (NR_MIXED_SLOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : free_tdd_configuration_nr
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#ifndef PHY_FRAME_CONFIG_NR_H
|
||||
#define PHY_FRAME_CONFIG_NR_H
|
||||
|
||||
#include <nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h>
|
||||
/************** DEFINE ********************************************/
|
||||
|
||||
#define TDD_CONFIG_NB_FRAMES (2)
|
||||
@@ -77,10 +76,9 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms);
|
||||
* @param frame_parms NR DL Frame parameters
|
||||
* @param nr_frame : frame number
|
||||
* @param nr_tti : slot number
|
||||
@returns nr_slot_t : downlink or uplink */
|
||||
@returns int : downlink, uplink or mixed slot type*/
|
||||
|
||||
nr_slot_t nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti);
|
||||
int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti);
|
||||
int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_tti);
|
||||
|
||||
/** \brief This function frees tdd configuration for nr
|
||||
* @param frame_parms NR DL Frame parameters
|
||||
|
||||
@@ -106,6 +106,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
|
||||
dlsch0_harq->start_symbol = dlsch_config_pdu->start_symbol;
|
||||
dlsch0_harq->dlDmrsSymbPos = dlsch_config_pdu->dlDmrsSymbPos;
|
||||
dlsch0_harq->dmrsConfigType = dlsch_config_pdu->dmrsConfigType;
|
||||
dlsch0_harq->n_dmrs_cdm_groups = dlsch_config_pdu->n_dmrs_cdm_groups;
|
||||
dlsch0_harq->mcs = dlsch_config_pdu->mcs;
|
||||
dlsch0_harq->rvidx = dlsch_config_pdu->rv;
|
||||
dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH;
|
||||
@@ -147,12 +148,32 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
|
||||
// pusch config pdu
|
||||
pusch_config_pdu = &ul_config->ul_config_list[i].pusch_config_pdu;
|
||||
current_harq_pid = pusch_config_pdu->pusch_data.harq_process_id;
|
||||
nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &ulsch0->harq_processes[current_harq_pid]->pusch_pdu;
|
||||
NR_UL_UE_HARQ_t *harq_process_ul_ue = ulsch0->harq_processes[current_harq_pid];
|
||||
|
||||
memcpy(pusch_pdu, pusch_config_pdu, sizeof(nfapi_nr_ue_pusch_pdu_t));
|
||||
if (harq_process_ul_ue){
|
||||
|
||||
nfapi_nr_ue_pusch_pdu_t *pusch_pdu = &harq_process_ul_ue->pusch_pdu;
|
||||
|
||||
memcpy(pusch_pdu, pusch_config_pdu, sizeof(nfapi_nr_ue_pusch_pdu_t));
|
||||
|
||||
ulsch0->f_pusch = pusch_config_pdu->absolute_delta_PUSCH;
|
||||
|
||||
if (scheduled_response->tx_request){
|
||||
fapi_nr_tx_request_body_t *tx_req_body = scheduled_response->tx_request->tx_request_body;
|
||||
|
||||
//harq_process_ul_ue->a = (unsigned char*)calloc(TBS/8, sizeof(unsigned char));
|
||||
memcpy(harq_process_ul_ue->a, tx_req_body->pdu, tx_req_body->pdu_length);
|
||||
|
||||
harq_process_ul_ue->status = ACTIVE;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
LOG_E(PHY, "[phy_procedures_nrUE_TX] harq_process_ul_ue is NULL !!\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
ulsch0->f_pusch = pusch_config_pdu->absolute_delta_PUSCH;
|
||||
ulsch0->harq_processes[current_harq_pid]->status = ACTIVE;
|
||||
break;
|
||||
|
||||
case (FAPI_NR_UL_CONFIG_TYPE_PUCCH):
|
||||
@@ -214,9 +235,6 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
|
||||
} else {
|
||||
}
|
||||
|
||||
if (scheduled_response->tx_request != NULL){
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -62,10 +62,18 @@ int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms);
|
||||
* @param frame_parms NR DL Frame parameters
|
||||
* @param nr_frame : frame number
|
||||
* @param nr_tti : slot number
|
||||
@returns nr_slot_t : downlink or uplink */
|
||||
@returns int : downlink or uplink */
|
||||
|
||||
int slot_select_nr(NR_DL_FRAME_PARMS *frame_parms, int nr_frame, int nr_tti);
|
||||
|
||||
/** \brief This function checks nr UE slot direction : downlink or uplink
|
||||
* @param cfg : FAPI Config Request
|
||||
* @param nr_frame : frame number
|
||||
* @param nr_tti : slot number
|
||||
@returns int : downlink, uplink or mixed slot type */
|
||||
|
||||
int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti);
|
||||
|
||||
/** \brief This function frees tdd configuration for nr
|
||||
* @param frame_parms NR DL Frame parameters
|
||||
@returns none */
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* FILENAME : phy_frame_configuration_nr_ue.c
|
||||
*
|
||||
* DESCRIPTION : functions related to FDD/TDD configuration for NR
|
||||
* see TS 38.213 11.1 Slot configuration
|
||||
* and TS 38.331 for RRC configuration
|
||||
*
|
||||
************************************************************************/
|
||||
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : nr_ue_slot_select
|
||||
*
|
||||
* DESCRIPTION : function for the UE equivalent to nr_slot_select
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_frame, int nr_tti) {
|
||||
/* for FFD all slot can be considered as an uplink */
|
||||
int mu = cfg->ssb_config.scs_common, check_slot = 0;
|
||||
|
||||
if (cfg->cell_config.frame_duplex_type == FDD) {
|
||||
return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT);
|
||||
}
|
||||
|
||||
if (nr_frame%2 == 0) {
|
||||
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) {
|
||||
check_slot++;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
|
||||
return (NR_UPLINK_SLOT);
|
||||
}
|
||||
|
||||
check_slot = 0;
|
||||
|
||||
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) {
|
||||
check_slot++;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
|
||||
return (NR_DOWNLINK_SLOT);
|
||||
} else {
|
||||
return (NR_MIXED_SLOT);
|
||||
}
|
||||
} else {
|
||||
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[((1<<mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) + nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) {
|
||||
check_slot++;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
|
||||
return (NR_UPLINK_SLOT);
|
||||
}
|
||||
|
||||
check_slot = 0;
|
||||
|
||||
for(int symbol_count=0; symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) {
|
||||
if (cfg->tdd_table.max_tdd_periodicity_list[((1<<mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) + nr_tti].max_num_of_symbol_per_slot_list[symbol_count].slot_config == 0) {
|
||||
check_slot++;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) {
|
||||
return (NR_DOWNLINK_SLOT);
|
||||
} else {
|
||||
return (NR_MIXED_SLOT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2269,7 +2269,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,
|
||||
|
||||
/* RACH */
|
||||
if (get_softmodem_params()->do_ra==1) {
|
||||
if ((ue->UE_mode[gNB_id] == PRACH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) {
|
||||
if ((ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) {
|
||||
nr_ue_prach_procedures(ue, proc, gNB_id, mode);
|
||||
}
|
||||
}
|
||||
@@ -3289,9 +3289,8 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
NR_UE_PDSCH *pdsch_vars;
|
||||
uint8_t is_cw0_active = 0;
|
||||
uint8_t is_cw1_active = 0;
|
||||
uint8_t dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType;
|
||||
uint8_t nb_re_dmrs = (dmrs_type==NFAPI_NR_DMRS_TYPE1)?6:4; // TODO: should changed my mac
|
||||
uint16_t length_dmrs = 1; //cfg->pdsch_config.dmrs_max_length.value;
|
||||
uint8_t dmrs_type, nb_re_dmrs;
|
||||
uint16_t length_dmrs = 1;
|
||||
uint16_t nb_symb_sch = 9;
|
||||
nr_downlink_indication_t dl_indication;
|
||||
fapi_nr_rx_indication_t rx_ind;
|
||||
@@ -3316,6 +3315,13 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
is_cw0_active = dlsch0->harq_processes[harq_pid]->status;
|
||||
nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols;
|
||||
start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol;
|
||||
dmrs_type = dlsch0->harq_processes[harq_pid]->dmrsConfigType;
|
||||
if (dmrs_type==NFAPI_NR_DMRS_TYPE1) {
|
||||
nb_re_dmrs = 6*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups;
|
||||
}
|
||||
else {
|
||||
nb_re_dmrs = 4*dlsch0->harq_processes[harq_pid]->n_dmrs_cdm_groups;
|
||||
}
|
||||
|
||||
if(dlsch1)
|
||||
is_cw1_active = dlsch1->harq_processes[harq_pid]->status;
|
||||
@@ -4606,6 +4612,8 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t
|
||||
|
||||
if (ue->prach_cnt == 3)
|
||||
ue->prach_cnt = 0;
|
||||
} else if (nr_prach == 2) {
|
||||
nr_ra_succeeded(mod_id, ue->CC_id, gNB_id);
|
||||
}
|
||||
|
||||
// if we're calibrating the PRACH kill the pointer to its resources so that the RA protocol doesn't continue
|
||||
|
||||
@@ -478,8 +478,9 @@ int main(int argc, char **argv)
|
||||
harq_process->Qm = mod_order;
|
||||
harq_process->rvidx = rvidx;
|
||||
harq_process->R = rate;
|
||||
harq_process->dmrsConfigType = 1;
|
||||
harq_process->dmrsConfigType = NFAPI_NR_DMRS_TYPE1;
|
||||
harq_process->dlDmrsSymbPos = 4;
|
||||
harq_process->n_dmrs_cdm_groups = 1;
|
||||
printf("harq process ue mcs = %d Qm = %d, symb %d\n", harq_process->mcs, harq_process->Qm, nb_symb_sch);
|
||||
unsigned char *test_input;
|
||||
test_input = (unsigned char *) malloc16(sizeof(unsigned char) * TBS / 8);
|
||||
|
||||
@@ -756,7 +756,8 @@ int main(int argc, char **argv)
|
||||
scheduled_response.slot = slot;
|
||||
scheduled_response.dl_config = NULL;
|
||||
scheduled_response.ul_config = &ul_config;
|
||||
scheduled_response.dl_config = NULL;
|
||||
scheduled_response.tx_request = (fapi_nr_tx_request_t *) malloc(sizeof(fapi_nr_tx_request_t));
|
||||
scheduled_response.tx_request->tx_request_body = (fapi_nr_tx_request_body_t *) malloc(sizeof(fapi_nr_tx_request_body_t));
|
||||
|
||||
ul_config.slot = slot;
|
||||
ul_config.number_pdus = 1;
|
||||
|
||||
@@ -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 tdl_a_delays[] = {0.0000,
|
||||
@@ -498,12 +503,24 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
double forgetting_factor,
|
||||
int32_t channel_offset,
|
||||
double path_loss_dB) {
|
||||
channel_desc_t *chan_desc = (channel_desc_t *)malloc(sizeof(channel_desc_t));
|
||||
channel_desc_t *chan_desc = (channel_desc_t *)calloc(1,sizeof(channel_desc_t));
|
||||
for(int i=0; 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;
|
||||
@@ -537,7 +554,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
|
||||
sum_amps = 0;
|
||||
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
|
||||
for (i = 0; i<chan_desc->nb_taps; i++) {
|
||||
chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]);
|
||||
sum_amps += chan_desc->amps[i];
|
||||
@@ -575,9 +592,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
for (i = 0; i<6; i++)
|
||||
chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0];
|
||||
} else {
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
|
||||
for (i = 0; i<6; i++) {
|
||||
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
|
||||
|
||||
|
||||
for (j = 0; 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;
|
||||
@@ -596,7 +614,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
|
||||
sum_amps = 0;
|
||||
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
|
||||
for (i = 0; i<chan_desc->nb_taps; i++) {
|
||||
chan_desc->amps[i] = pow(10,.1*scm_c_amps_dB[i]);
|
||||
sum_amps += chan_desc->amps[i];
|
||||
@@ -634,6 +652,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
for (i = 0; i<6; i++)
|
||||
chan_desc->R_sqrt[i] = (struct complex *) &R12_sqrt[i][0];
|
||||
} else {
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
|
||||
for (i = 0; i<6; i++) {
|
||||
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
|
||||
|
||||
@@ -647,6 +666,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
}
|
||||
|
||||
break;
|
||||
<<<<<<< HEAD
|
||||
|
||||
case TDL_A:
|
||||
case TDL_B:
|
||||
@@ -742,13 +762,16 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
|
||||
break;
|
||||
|
||||
=======
|
||||
|
||||
>>>>>>> origin/develop
|
||||
case EPA:
|
||||
chan_desc->nb_taps = 7;
|
||||
chan_desc->Td = .410;
|
||||
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
|
||||
sum_amps = 0;
|
||||
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
|
||||
for (i = 0; i<chan_desc->nb_taps; i++) {
|
||||
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
|
||||
sum_amps += chan_desc->amps[i];
|
||||
@@ -767,7 +790,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
|
||||
for (i = 0; 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));
|
||||
|
||||
@@ -781,7 +804,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
|
||||
} else {
|
||||
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
|
||||
for (i = 0; i<6; i++) {
|
||||
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
|
||||
|
||||
@@ -802,7 +825,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
|
||||
sum_amps = 0;
|
||||
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
|
||||
for (i = 0; i<chan_desc->nb_taps; i++) {
|
||||
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
|
||||
sum_amps += chan_desc->amps[i];
|
||||
@@ -848,7 +871,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
LOG_W(OCM,"correlation matrix only implemented for nb_tx==2 and nb_rx==2, using identity\n");
|
||||
}
|
||||
}*/
|
||||
break;
|
||||
break;
|
||||
|
||||
case EPA_high:
|
||||
chan_desc->nb_taps = 7;
|
||||
@@ -856,7 +879,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
|
||||
sum_amps = 0;
|
||||
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
|
||||
for (i = 0; i<chan_desc->nb_taps; i++) {
|
||||
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
|
||||
sum_amps += chan_desc->amps[i];
|
||||
@@ -910,7 +933,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
|
||||
sum_amps = 0;
|
||||
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
|
||||
for (i = 0; i<chan_desc->nb_taps; i++) {
|
||||
chan_desc->amps[i] = pow(10,.1*epa_amps_dB[i]);
|
||||
sum_amps += chan_desc->amps[i];
|
||||
@@ -964,7 +987,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
|
||||
sum_amps = 0;
|
||||
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
|
||||
for (i = 0; i<chan_desc->nb_taps; i++) {
|
||||
chan_desc->amps[i] = pow(10,.1*eva_amps_dB[i]);
|
||||
sum_amps += chan_desc->amps[i];
|
||||
@@ -997,8 +1020,8 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
|
||||
} else {
|
||||
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
|
||||
|
||||
for (i = 0; i<6; i++) {
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
|
||||
for (i = 0; i<6; i++) {
|
||||
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
|
||||
|
||||
for (j = 0; j<nb_tx*nb_rx*nb_tx*nb_rx; j+=(nb_tx*nb_rx+1)) {
|
||||
@@ -1018,7 +1041,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];
|
||||
@@ -1051,7 +1074,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->R_sqrt[i] = (struct complex *) &R22_sqrt[i][0];
|
||||
} else {
|
||||
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex **));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6 ;
|
||||
for (i = 0; i<6; i++) {
|
||||
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
|
||||
|
||||
@@ -1072,7 +1095,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->channel_length = (int) (2*chan_desc->sampling_rate*chan_desc->Td + 1 + 2/(M_PI*M_PI)*log(4*M_PI*chan_desc->sampling_rate*chan_desc->Td));
|
||||
sum_amps = 0;
|
||||
chan_desc->amps = (double *) malloc(chan_desc->nb_taps*sizeof(double));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_AMPS ;
|
||||
for (i = 0; i<chan_desc->nb_taps; i++) {
|
||||
chan_desc->amps[i] = pow(10,.1*mbsfn_amps_dB[i]);
|
||||
sum_amps += chan_desc->amps[i];
|
||||
@@ -1099,7 +1122,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->a[i] = (struct complex *) malloc(nb_tx*nb_rx * sizeof(struct complex));
|
||||
|
||||
chan_desc->R_sqrt = (struct complex **) malloc(6*sizeof(struct complex *));
|
||||
|
||||
chan_desc->free_flags=chan_desc->free_flags|CHANMODEL_FREE_RSQRT_6;
|
||||
for (i = 0; i<6; i++) {
|
||||
chan_desc->R_sqrt[i] = (struct complex *) malloc(nb_tx*nb_rx*nb_tx*nb_rx * sizeof(struct complex));
|
||||
|
||||
@@ -1610,10 +1633,37 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
chan_desc->nb_paths = 10;
|
||||
return(chan_desc);
|
||||
}
|
||||
|
||||
|
||||
void free_channel_desc_scm(channel_desc_t *ch) {
|
||||
// Must be made cleanly, a lot of leaks...
|
||||
free(ch);
|
||||
defined_channels[ch->chan_idx]=NULL;
|
||||
if(ch->free_flags&CHANMODEL_FREE_AMPS)
|
||||
free(ch->amps);
|
||||
for (int i = 0; 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) {
|
||||
@@ -1726,11 +1776,11 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
|
||||
desc->ch[aarx+(aatx*desc->nb_rx)][k].y = 0.0;
|
||||
|
||||
for (l=0; 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;
|
||||
@@ -1753,7 +1803,7 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) {
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
double N_RB2sampling_rate(uint16_t N_RB) {
|
||||
double sampling_rate;
|
||||
|
||||
@@ -1805,22 +1855,125 @@ double N_RB2channel_bandwidth(uint16_t N_RB) {
|
||||
LOG_E(PHY,"Unknown N_PRB\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(channel_bandwidth);
|
||||
}
|
||||
|
||||
|
||||
static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt ) {
|
||||
prnt("channelmod commands can be used to display or modify channel models parameters\n");
|
||||
prnt("channelmod show predef: display predefined model algorithms available in oai\n");
|
||||
prnt("channelmod show current: display the currently used models in the running executable\n");
|
||||
prnt("channelmod modify <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);
|
||||
|
||||
return 0;
|
||||
if (s>0) {
|
||||
if ( strcmp(subcmd,"predef") == 0) {
|
||||
for (int i=0; channelmod_names[i].name != NULL ; i++) {
|
||||
prnt(" %i %s\n", i, map_int_to_str(channelmod_names,i ));
|
||||
}
|
||||
} else if ( strcmp(subcmd,"current") == 0) {
|
||||
for (int i=0; i < max_chan ; i++) {
|
||||
if (defined_channels[i] != NULL) {
|
||||
prnt("model %i %s: \n----------------\n", i, map_int_to_str(channelmod_names,defined_channels[i]->modelid));
|
||||
display_channelmodel(defined_channels[i],debug,prnt);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channelmod_print_help(buff, debug, prnt);
|
||||
}
|
||||
free(subcmd);
|
||||
}
|
||||
return CMDSTATUS_FOUND;
|
||||
}
|
||||
|
||||
int modelid_fromname(char *modelname) {
|
||||
int modelid=map_str_to_int(channelmod_names,modelname);
|
||||
AssertFatal(modelid>0,
|
||||
"random_channel.c: Error channel model %s unknown\n",modelname);
|
||||
|
||||
|
||||
static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt) {
|
||||
char *param=NULL, *value=NULL;
|
||||
int cd_id= -1;
|
||||
int s = sscanf(buff,"%i %ms %ms \n",&cd_id,¶m, &value);
|
||||
if (cd_id<0 || cd_id >= max_chan) {
|
||||
prnt("ERROR, %i: Channel model id outof range (0-%i)\n",cd_id,max_chan-1);
|
||||
return CMDSTATUS_FOUND;
|
||||
}
|
||||
if (defined_channels[cd_id]==NULL) {
|
||||
prnt("ERROR, %i: Channel model has not been set\n",cd_id);
|
||||
return CMDSTATUS_FOUND;
|
||||
}
|
||||
|
||||
if (s==3) {
|
||||
if ( strcmp(param,"riceanf") == 0) {
|
||||
double dbl = atof(value);
|
||||
if (dbl <0 || dbl > 1)
|
||||
prnt("ERROR: ricean factor range: 0 to 1, %lf is outof range\n",dbl);
|
||||
else
|
||||
defined_channels[cd_id]->ricean_factor=dbl;
|
||||
} else if ( strcmp(param,"aoa") == 0) {
|
||||
double dbl = atof(value);
|
||||
if (dbl <0 || dbl >6.28)
|
||||
prnt("ERROR: angle of arrival range: 0 to 2*Pi, %lf is outof range\n",dbl);
|
||||
else
|
||||
defined_channels[cd_id]->aoa=dbl;
|
||||
} else if ( strcmp(param,"randaoa") == 0) {
|
||||
int i = atoi(value);
|
||||
if (i!=0 && i!=1)
|
||||
prnt("ERROR: randaoa is a boolean, must be 0 or 1\n");
|
||||
else
|
||||
defined_channels[cd_id]->random_aoa=i;
|
||||
} else if ( strcmp(param,"ploss") == 0) {
|
||||
double dbl = atof(value);
|
||||
defined_channels[cd_id]->path_loss_dB=dbl;
|
||||
} else if ( strcmp(param,"offset") == 0) {
|
||||
int i = atoi(value);
|
||||
defined_channels[cd_id]->channel_offset=i;
|
||||
} else if ( strcmp(param,"forgetf") == 0) {
|
||||
double dbl = atof(value);
|
||||
if (dbl <0 || dbl > 1)
|
||||
prnt("ERROR: forgetting factor range: 0 to 1 (disable variation), %lf is outof range\n",dbl);
|
||||
else
|
||||
defined_channels[cd_id]->forgetting_factor=dbl;
|
||||
} else {
|
||||
prnt("ERROR: %s, unknown channel parameter\n",param);
|
||||
return CMDSTATUS_FOUND;
|
||||
}
|
||||
display_channelmodel(defined_channels[cd_id],debug,prnt);
|
||||
free(param);
|
||||
free(value);
|
||||
random_channel(defined_channels[cd_id],false);
|
||||
}
|
||||
return CMDSTATUS_FOUND;
|
||||
}
|
||||
|
||||
int modelid_fromname(char *modelname) {
|
||||
int modelid=map_str_to_int(channelmod_names,modelname);
|
||||
if (modelid < 0)
|
||||
LOG_E(OCM,"random_channel.c: Error channel model %s unknown\n",modelname);
|
||||
return modelid;
|
||||
}
|
||||
|
||||
@@ -1836,6 +1989,9 @@ void init_channelmod(void) {
|
||||
paramdef_t channelmod_params[] = CHANNELMOD_PARAMS_DESC;
|
||||
int ret = config_get( channelmod_params,sizeof(channelmod_params)/sizeof(paramdef_t),CHANNELMOD_SECTION);
|
||||
AssertFatal(ret >= 0, "configuration couldn't be performed");
|
||||
defined_channels=calloc(max_chan,sizeof( channel_desc_t*));
|
||||
AssertFatal(defined_channels!=NULL, "couldn't allocate %u channel descriptors\n",max_chan);
|
||||
|
||||
/* look for telnet server, if it is loaded, add the channel modeling commands to it */
|
||||
add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME);
|
||||
|
||||
|
||||
@@ -40,6 +40,16 @@ The present clause specifies several numerical functions for testing of digital
|
||||
|
||||
#define NB_SAMPLES_CHANNEL_OFFSET 4
|
||||
|
||||
typedef enum {
|
||||
UNSPECIFIED_MODID=0,
|
||||
RFSIMU_MODULEID=1
|
||||
} channelmod_moduleid_t;
|
||||
#define MODULEID_STR_INIT {"","rfsimulator"}
|
||||
|
||||
#define CHANMODEL_FREE_DELAY 1<<0
|
||||
#define CHANMODEL_FREE_RSQRT_6 1<<1
|
||||
#define CHANMODEL_FREE_RSQRT_NTAPS 1<<2
|
||||
#define CHANMODEL_FREE_AMPS 1<<3
|
||||
typedef struct {
|
||||
///Number of tx antennas
|
||||
uint8_t nb_tx;
|
||||
@@ -92,6 +102,14 @@ typedef struct {
|
||||
time_stats_t interp_time;
|
||||
time_stats_t interp_freq;
|
||||
time_stats_t convolution;
|
||||
/// index in the channel descriptors array
|
||||
unsigned int chan_idx;
|
||||
/// id of the channel modeling algorithm
|
||||
int modelid;
|
||||
/// identifies channel descriptor owner (the module which created this descriptor)
|
||||
channelmod_moduleid_t module_id;
|
||||
/// flags to properly trigger memory free
|
||||
unsigned int free_flags;
|
||||
} channel_desc_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -224,8 +242,9 @@ typedef enum {
|
||||
#define CONFIG_HLP_SNR "Set average SNR in dB (for --siml1 option)\n"
|
||||
#define CHANNELMOD_SECTION "channelmod"
|
||||
#define CHANNELMOD_PARAMS_DESC { \
|
||||
{"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB , defdblval:25, TYPE_DOUBLE, 0},\
|
||||
{"sinr_dB", NULL , 0 , dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\
|
||||
{"s" , CONFIG_HLP_SNR, PARAMFLAG_CMDLINE_NOPREFIXENABLED, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0},\
|
||||
{"sinr_dB", NULL, 0 , dblptr:&sinr_dB, defdblval:0 , TYPE_DOUBLE, 0},\
|
||||
{"max_chan, CONFIG_HLP_MAX_CHAN", 0, uptr:&max_chan, defintval:10, TYPE_UINT, 0},\
|
||||
}
|
||||
|
||||
#include "platform_constants.h"
|
||||
@@ -262,9 +281,18 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
|
||||
double forgetting_factor,
|
||||
int32_t channel_offset,
|
||||
double path_loss_dB);
|
||||
/**
|
||||
\brief free memory allocated for a model descriptor
|
||||
\param ch points to the model, which cannot be used after calling this fuction
|
||||
*/
|
||||
void free_channel_desc_scm(channel_desc_t *ch);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief This set the ownerid of a model descriptor, can be later used to check what module created a channel model
|
||||
\param cdesc points to the model descriptor
|
||||
\param module_id identifies the channel model. should be define as a macro in simu.h
|
||||
*/
|
||||
void set_channeldesc_owner(channel_desc_t *cdesc, channelmod_moduleid_t module_id);
|
||||
/** \fn void random_channel(channel_desc_t *desc)
|
||||
\brief This routine generates a random channel response (time domain) according to a tapped delay line model.
|
||||
\param desc Pointer to the channel descriptor
|
||||
|
||||
@@ -49,18 +49,13 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
/* the slice config as kept in the underlying system */
|
||||
Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES];
|
||||
/* a structure that keeps updates which will be reflected in slice_config later */
|
||||
Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES];
|
||||
/* indicates whether sc_update contains new data */
|
||||
int perform_slice_config_update_count = 1;
|
||||
/* queue of incoming new UE<>slice association commands */
|
||||
Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES];
|
||||
int n_ue_slice_assoc_updates = 0;
|
||||
/* mutex for sc_update: do not receive new config and write it at the same time */
|
||||
pthread_mutex_t sc_update_mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
/* Ringbuffer-related to slice configuration */
|
||||
struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
/* Ringbuffer-related to slice configuration */
|
||||
struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB];
|
||||
struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB];
|
||||
|
||||
int flexran_agent_mac_stats_reply_ue(mid_t mod_id,
|
||||
Protocol__FlexUeStatsReport **ue_report,
|
||||
@@ -1354,6 +1349,33 @@ void flexran_agent_init_mac_agent(mid_t mod_id) {
|
||||
AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory for lfds library\n");
|
||||
lfds700_ringbuffer_init_valid_on_current_logical_core(&ringbuffer_state[mod_id],
|
||||
dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL);
|
||||
|
||||
struct lfds700_misc_prng_state scrng;
|
||||
i = posix_memalign((void **) &slice_config_array[mod_id],
|
||||
LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES,
|
||||
sizeof(struct lfds700_ringbuffer_element) * num_elements);
|
||||
AssertFatal(i == 0,
|
||||
"posix_memalign(): could not allocate aligned memory\n");
|
||||
lfds700_ringbuffer_init_valid_on_current_logical_core(
|
||||
&slice_config_ringbuffer_state[mod_id],
|
||||
slice_config_array[mod_id],
|
||||
num_elements,
|
||||
&scrng,
|
||||
NULL);
|
||||
|
||||
struct lfds700_misc_prng_state uarng;
|
||||
i = posix_memalign((void **) &ue_assoc_array[mod_id],
|
||||
LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES,
|
||||
sizeof(struct lfds700_ringbuffer_element) * num_elements);
|
||||
AssertFatal(i == 0,
|
||||
"posix_memalign(): could not allocate aligned memory\n");
|
||||
lfds700_ringbuffer_init_valid_on_current_logical_core(
|
||||
&ue_assoc_ringbuffer_state[mod_id],
|
||||
ue_assoc_array[mod_id],
|
||||
num_elements,
|
||||
&uarng,
|
||||
NULL);
|
||||
|
||||
for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (RC.mac && RC.mac[mod_id])
|
||||
@@ -1465,9 +1487,74 @@ void flexran_agent_fill_mac_cell_config(mid_t mod_id, uint8_t cc_id,
|
||||
conf->si_config->has_sfn = 1;
|
||||
}
|
||||
|
||||
/* get a pointer to the config which is maintained in the agent throughout
|
||||
* its lifetime */
|
||||
conf->slice_config = flexran_agent_get_slice_config(mod_id);
|
||||
conf->slice_config = malloc(sizeof(Protocol__FlexSliceConfig));
|
||||
if (conf->slice_config) {
|
||||
protocol__flex_slice_config__init(conf->slice_config);
|
||||
Protocol__FlexSliceConfig *sc = conf->slice_config;
|
||||
|
||||
sc->dl = malloc(sizeof(Protocol__FlexSliceDlUlConfig));
|
||||
DevAssert(sc->dl);
|
||||
protocol__flex_slice_dl_ul_config__init(sc->dl);
|
||||
sc->dl->algorithm = flexran_get_dl_slice_algo(mod_id);
|
||||
sc->dl->has_algorithm = 1;
|
||||
sc->dl->n_slices = flexran_get_num_dl_slices(mod_id);
|
||||
if (sc->dl->n_slices > 0) {
|
||||
sc->dl->slices = calloc(sc->dl->n_slices, sizeof(Protocol__FlexSlice *));
|
||||
DevAssert(sc->dl->slices);
|
||||
for (int i = 0; i < sc->dl->n_slices; ++i) {
|
||||
sc->dl->slices[i] = malloc(sizeof(Protocol__FlexSlice));
|
||||
DevAssert(sc->dl->slices[i]);
|
||||
protocol__flex_slice__init(sc->dl->slices[i]);
|
||||
flexran_get_dl_slice(mod_id, i, sc->dl->slices[i], sc->dl->algorithm);
|
||||
}
|
||||
} else {
|
||||
sc->dl->scheduler = flexran_get_dl_scheduler_name(mod_id);
|
||||
}
|
||||
|
||||
sc->ul = malloc(sizeof(Protocol__FlexSliceDlUlConfig));
|
||||
DevAssert(sc->ul);
|
||||
protocol__flex_slice_dl_ul_config__init(sc->ul);
|
||||
sc->ul->algorithm = flexran_get_ul_slice_algo(mod_id);
|
||||
sc->ul->has_algorithm = 1;
|
||||
sc->ul->n_slices = flexran_get_num_ul_slices(mod_id);
|
||||
if (sc->ul->n_slices > 0) {
|
||||
sc->ul->slices = calloc(sc->ul->n_slices, sizeof(Protocol__FlexSlice *));
|
||||
DevAssert(sc->ul->slices);
|
||||
for (int i = 0; i < sc->ul->n_slices; ++i) {
|
||||
sc->ul->slices[i] = malloc(sizeof(Protocol__FlexSlice));
|
||||
DevAssert(sc->ul->slices[i]);
|
||||
protocol__flex_slice__init(sc->ul->slices[i]);
|
||||
flexran_get_ul_slice(mod_id, i, sc->ul->slices[i], sc->ul->algorithm);
|
||||
}
|
||||
} else {
|
||||
sc->ul->scheduler = flexran_get_ul_scheduler_name(mod_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf) {
|
||||
Protocol__FlexSliceConfig *sc = conf->slice_config;
|
||||
for (int i = 0; i < sc->dl->n_slices; ++i) {
|
||||
free(sc->dl->slices[i]);
|
||||
sc->dl->slices[i] = NULL;
|
||||
/* scheduler names are not freed: we assume we read them directly from the
|
||||
* underlying memory and do not dispose it */
|
||||
}
|
||||
free(sc->dl->slices);
|
||||
/* scheduler name is not freed */
|
||||
free(sc->dl);
|
||||
sc->dl = NULL;
|
||||
for (int i = 0; i < sc->ul->n_slices; ++i) {
|
||||
free(sc->ul->slices[i]);
|
||||
sc->ul->slices[i] = NULL;
|
||||
/* scheduler names are not freed */
|
||||
}
|
||||
free(sc->ul->slices);
|
||||
/* scheduler name is not freed */
|
||||
free(sc->ul);
|
||||
sc->ul = NULL;
|
||||
free(conf->slice_config);
|
||||
conf->slice_config = NULL;
|
||||
}
|
||||
|
||||
void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id,
|
||||
@@ -1481,10 +1568,12 @@ void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id,
|
||||
ue_conf->rnti = flexran_get_mac_ue_crnti(mod_id, ue_id);
|
||||
ue_conf->has_rnti = 1;
|
||||
|
||||
ue_conf->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, ue_id);
|
||||
ue_conf->has_dl_slice_id = 1;
|
||||
ue_conf->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, ue_id);
|
||||
ue_conf->has_ul_slice_id = 1;
|
||||
int dl_id = flexran_get_ue_dl_slice_id(mod_id, ue_id);
|
||||
ue_conf->dl_slice_id = dl_id;
|
||||
ue_conf->has_dl_slice_id = dl_id >= 0;
|
||||
int ul_id = flexran_get_ue_ul_slice_id(mod_id, ue_id);
|
||||
ue_conf->ul_slice_id = ul_id;
|
||||
ue_conf->has_ul_slice_id = ul_id >= 0;
|
||||
|
||||
ue_conf->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id, ue_id);
|
||||
ue_conf->has_ue_aggregated_max_bitrate_ul = 1;
|
||||
@@ -1565,6 +1654,15 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id)
|
||||
LOG_E(FLEXRAN_AGENT, "MAC agent CM for eNB %d is not registered\n", mod_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lfds700_ringbuffer_cleanup(&ringbuffer_state[mod_id], NULL );
|
||||
free(dl_mac_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL );
|
||||
free(slice_config_array[mod_id]);
|
||||
lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL );
|
||||
free(ue_assoc_array[mod_id]);
|
||||
lfds700_misc_library_cleanup();
|
||||
|
||||
AGENT_MAC_xface *xface = agent_mac_xface[mod_id];
|
||||
xface->flexran_agent_send_sr_info = NULL;
|
||||
xface->flexran_agent_send_sf_trigger = NULL;
|
||||
@@ -1579,230 +1677,91 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void flexran_create_config_structures(mid_t mod_id)
|
||||
{
|
||||
int i;
|
||||
int n_dl = flexran_get_num_dl_slices(mod_id);
|
||||
int m_ul = flexran_get_num_ul_slices(mod_id);
|
||||
slice_config[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
|
||||
sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul);
|
||||
if (!slice_config[mod_id] || !sc_update[mod_id]) return;
|
||||
|
||||
flexran_agent_read_slice_config(mod_id, slice_config[mod_id]);
|
||||
flexran_agent_read_slice_config(mod_id, sc_update[mod_id]);
|
||||
for (i = 0; i < n_dl; i++) {
|
||||
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
|
||||
flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]);
|
||||
void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) {
|
||||
if (slice_config->dl) {
|
||||
if (slice_config->dl->scheduler)
|
||||
free(slice_config->dl->scheduler);
|
||||
for (int i = 0; i < slice_config->dl->n_slices; i++)
|
||||
if (slice_config->dl->slices[i]->scheduler)
|
||||
free(slice_config->dl->slices[i]->scheduler);
|
||||
}
|
||||
for (i = 0; i < m_ul; i++) {
|
||||
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
|
||||
flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]);
|
||||
if (slice_config->ul) {
|
||||
if (slice_config->ul->scheduler)
|
||||
free(slice_config->ul->scheduler);
|
||||
for (int i = 0; i < slice_config->ul->n_slices; i++)
|
||||
if (slice_config->ul->slices[i]->scheduler)
|
||||
free(slice_config->ul->slices[i]->scheduler);
|
||||
}
|
||||
|
||||
Protocol__FlexCellConfig helper;
|
||||
helper.slice_config = slice_config;
|
||||
flexran_agent_destroy_mac_slice_config(&helper);
|
||||
}
|
||||
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) {
|
||||
if (!*slice_config) return;
|
||||
/* just use the memory and set to NULL in original */
|
||||
Protocol__FlexSliceConfig *sc = *slice_config;
|
||||
*slice_config = NULL;
|
||||
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
enum lfds700_misc_flag overwrite_occurred_flag;
|
||||
|
||||
Protocol__FlexSliceConfig *overwritten_sc;
|
||||
lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id],
|
||||
NULL,
|
||||
(void *)sc,
|
||||
&overwrite_occurred_flag,
|
||||
NULL,
|
||||
(void **)&overwritten_sc,
|
||||
&ls);
|
||||
|
||||
if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
|
||||
helper_destroy_mac_slice_config(overwritten_sc);
|
||||
LOG_E(FLEXRAN_AGENT, "lost slice config: too many reconfigurations at once\n");
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_check_and_remove_slices(mid_t mod_id)
|
||||
{
|
||||
Protocol__FlexDlSlice **dl = sc_update[mod_id]->dl;
|
||||
Protocol__FlexDlSlice **dlreal = slice_config[mod_id]->dl;
|
||||
int i = 0;
|
||||
while (i < sc_update[mod_id]->n_dl) {
|
||||
/* remove slices whose percentage is zero */
|
||||
if (dl[i]->percentage > 0) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (flexran_remove_dl_slice(mod_id, i) < 1) {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n",
|
||||
mod_id, i, dl[i]->id);
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
|
||||
mod_id, i, dl[i]->id);
|
||||
if (dl[i]->n_sorting > 0) free(dl[i]->sorting);
|
||||
free(dl[i]->scheduler_name);
|
||||
if (dlreal[i]->n_sorting > 0) {
|
||||
dlreal[i]->n_sorting = 0;
|
||||
free(dlreal[i]->sorting);
|
||||
}
|
||||
free(dlreal[i]->scheduler_name);
|
||||
--sc_update[mod_id]->n_dl;
|
||||
--slice_config[mod_id]->n_dl;
|
||||
const size_t last = sc_update[mod_id]->n_dl;
|
||||
/* we need to memcpy the higher slice to the position we just deleted */
|
||||
memcpy(dl[i], dl[last], sizeof(*dl[last]));
|
||||
memset(dl[last], 0, sizeof(*dl[last]));
|
||||
memcpy(dlreal[i], dlreal[last], sizeof(*dlreal[last]));
|
||||
memset(dlreal[last], 0, sizeof(*dlreal[last]));
|
||||
/* dont increase i but recheck the slice which has been copied to here */
|
||||
}
|
||||
Protocol__FlexUlSlice **ul = sc_update[mod_id]->ul;
|
||||
Protocol__FlexUlSlice **ulreal = slice_config[mod_id]->ul;
|
||||
i = 0;
|
||||
while (i < sc_update[mod_id]->n_ul) {
|
||||
if (ul[i]->percentage > 0) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
if (flexran_remove_ul_slice(mod_id, i) < 1) {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n",
|
||||
mod_id, i, ul[i]->id);
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n",
|
||||
mod_id, i, ul[i]->id);
|
||||
free(ul[i]->scheduler_name);
|
||||
free(ulreal[i]->scheduler_name);
|
||||
--sc_update[mod_id]->n_ul;
|
||||
--slice_config[mod_id]->n_ul;
|
||||
const size_t last = sc_update[mod_id]->n_ul;
|
||||
/* see DL remarks */
|
||||
memcpy(ul[i], ul[last], sizeof(*ul[last]));
|
||||
memset(ul[last], 0, sizeof(*ul[last]));
|
||||
memcpy(ulreal[i], ulreal[last], sizeof(*ulreal[last]));
|
||||
memset(ulreal[last], 0, sizeof(*ulreal[last]));
|
||||
/* dont increase i but recheck the slice which has been copied to here */
|
||||
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config) {
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
enum lfds700_misc_flag overwrite_occurred_flag;
|
||||
|
||||
Protocol__FlexUeConfig *overwritten_ue_config;
|
||||
lfds700_ringbuffer_write(&ue_assoc_ringbuffer_state[mod_id],
|
||||
NULL,
|
||||
(void *) *ue_config,
|
||||
&overwrite_occurred_flag,
|
||||
NULL,
|
||||
(void **)&overwritten_ue_config,
|
||||
&ls);
|
||||
|
||||
if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) {
|
||||
free(overwritten_ue_config);
|
||||
LOG_E(FLEXRAN_AGENT, "lost UE-slice association: too many UE-slice associations at once\n");
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_slice_update(mid_t mod_id)
|
||||
{
|
||||
int i;
|
||||
int changes = 0;
|
||||
void flexran_agent_slice_update(mid_t mod_id) {
|
||||
struct lfds700_misc_prng_state ls;
|
||||
LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
|
||||
lfds700_misc_prng_init(&ls);
|
||||
|
||||
if (perform_slice_config_update_count <= 0) return;
|
||||
perform_slice_config_update_count--;
|
||||
|
||||
pthread_mutex_lock(&sc_update_mtx);
|
||||
|
||||
if (!slice_config[mod_id]) {
|
||||
/* if the configuration does not exist for agent, create from eNB structure
|
||||
* and exit */
|
||||
flexran_create_config_structures(mod_id);
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
return;
|
||||
Protocol__FlexSliceConfig *sc = NULL;
|
||||
struct lfds700_ringbuffer_state *state = &slice_config_ringbuffer_state[mod_id];
|
||||
if (lfds700_ringbuffer_read(state, NULL, (void **) &sc, &ls) != 0) {
|
||||
apply_update_dl_slice_config(mod_id, sc->dl);
|
||||
apply_update_ul_slice_config(mod_id, sc->ul);
|
||||
helper_destroy_mac_slice_config(sc);
|
||||
}
|
||||
|
||||
/********* read existing config *********/
|
||||
/* simply update slice_config all the time and write new config
|
||||
* (apply_new_slice_dl_config() only updates if changes are necessary) */
|
||||
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
|
||||
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
|
||||
for (i = 0; i < slice_config[mod_id]->n_dl; i++) {
|
||||
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
|
||||
Protocol__FlexUeConfig *ue_config = NULL;
|
||||
state = &ue_assoc_ringbuffer_state[mod_id];
|
||||
if (lfds700_ringbuffer_read(state, NULL, (void **) &ue_config, &ls) != 0) {
|
||||
apply_ue_slice_assoc_update(mod_id, ue_config);
|
||||
free(ue_config);
|
||||
}
|
||||
for (i = 0; i < slice_config[mod_id]->n_ul; i++) {
|
||||
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
|
||||
}
|
||||
|
||||
/********* write new config *********/
|
||||
/* check for removal (sc_update[X]->dl[Y].percentage == 0)
|
||||
* and update sc_update & slice_config accordingly */
|
||||
flexran_check_and_remove_slices(mod_id);
|
||||
|
||||
/* create new DL and UL slices if necessary */
|
||||
for (i = slice_config[mod_id]->n_dl; i < sc_update[mod_id]->n_dl; i++) {
|
||||
flexran_create_dl_slice(mod_id, sc_update[mod_id]->dl[i]->id);
|
||||
}
|
||||
for (i = slice_config[mod_id]->n_ul; i < sc_update[mod_id]->n_ul; i++) {
|
||||
flexran_create_ul_slice(mod_id, sc_update[mod_id]->ul[i]->id);
|
||||
}
|
||||
slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id);
|
||||
slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id);
|
||||
changes += apply_new_slice_config(mod_id, slice_config[mod_id], sc_update[mod_id]);
|
||||
for (i = 0; i < slice_config[mod_id]->n_dl; i++) {
|
||||
changes += apply_new_slice_dl_config(mod_id,
|
||||
slice_config[mod_id]->dl[i],
|
||||
sc_update[mod_id]->dl[i]);
|
||||
flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]);
|
||||
}
|
||||
for (i = 0; i < slice_config[mod_id]->n_ul; i++) {
|
||||
changes += apply_new_slice_ul_config(mod_id,
|
||||
slice_config[mod_id]->ul[i],
|
||||
sc_update[mod_id]->ul[i]);
|
||||
flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]);
|
||||
}
|
||||
flexran_agent_read_slice_config(mod_id, slice_config[mod_id]);
|
||||
if (n_ue_slice_assoc_updates > 0) {
|
||||
changes += apply_ue_slice_assoc_update(mod_id);
|
||||
}
|
||||
if (changes > 0)
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] slice configuration: applied %d changes\n", mod_id, changes);
|
||||
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
}
|
||||
|
||||
Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id)
|
||||
{
|
||||
if (!slice_config[mod_id]) return NULL;
|
||||
Protocol__FlexSliceConfig *config = NULL;
|
||||
|
||||
pthread_mutex_lock(&sc_update_mtx);
|
||||
config = flexran_agent_create_slice_config(slice_config[mod_id]->n_dl,
|
||||
slice_config[mod_id]->n_ul);
|
||||
if (!config) {
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
return NULL;
|
||||
}
|
||||
config->has_intraslice_share_active = 1;
|
||||
config->intraslice_share_active = slice_config[mod_id]->intraslice_share_active;
|
||||
config->has_interslice_share_active = 1;
|
||||
config->interslice_share_active = slice_config[mod_id]->interslice_share_active;
|
||||
for (int i = 0; i < slice_config[mod_id]->n_dl; ++i) {
|
||||
if (!config->dl[i]) continue;
|
||||
config->dl[i]->has_id = 1;
|
||||
config->dl[i]->id = slice_config[mod_id]->dl[i]->id;
|
||||
config->dl[i]->has_label = 1;
|
||||
config->dl[i]->label = slice_config[mod_id]->dl[i]->label;
|
||||
config->dl[i]->has_percentage = 1;
|
||||
config->dl[i]->percentage = slice_config[mod_id]->dl[i]->percentage;
|
||||
config->dl[i]->has_isolation = 1;
|
||||
config->dl[i]->isolation = slice_config[mod_id]->dl[i]->isolation;
|
||||
config->dl[i]->has_priority = 1;
|
||||
config->dl[i]->priority = slice_config[mod_id]->dl[i]->priority;
|
||||
config->dl[i]->has_position_low = 1;
|
||||
config->dl[i]->position_low = slice_config[mod_id]->dl[i]->position_low;
|
||||
config->dl[i]->has_position_high = 1;
|
||||
config->dl[i]->position_high = slice_config[mod_id]->dl[i]->position_high;
|
||||
config->dl[i]->has_maxmcs = 1;
|
||||
config->dl[i]->maxmcs = slice_config[mod_id]->dl[i]->maxmcs;
|
||||
config->dl[i]->n_sorting = slice_config[mod_id]->dl[i]->n_sorting;
|
||||
config->dl[i]->sorting = calloc(config->dl[i]->n_sorting, sizeof(Protocol__FlexDlSorting));
|
||||
if (!config->dl[i]->sorting) config->dl[i]->n_sorting = 0;
|
||||
for (int j = 0; j < config->dl[i]->n_sorting; ++j)
|
||||
config->dl[i]->sorting[j] = slice_config[mod_id]->dl[i]->sorting[j];
|
||||
config->dl[i]->has_accounting = 1;
|
||||
config->dl[i]->accounting = slice_config[mod_id]->dl[i]->accounting;
|
||||
config->dl[i]->scheduler_name = strdup(slice_config[mod_id]->dl[i]->scheduler_name);
|
||||
}
|
||||
for (int i = 0; i < slice_config[mod_id]->n_ul; ++i) {
|
||||
if (!config->ul[i]) continue;
|
||||
config->ul[i]->has_id = 1;
|
||||
config->ul[i]->id = slice_config[mod_id]->ul[i]->id;
|
||||
config->ul[i]->has_label = 1;
|
||||
config->ul[i]->label = slice_config[mod_id]->ul[i]->label;
|
||||
config->ul[i]->has_percentage = 1;
|
||||
config->ul[i]->percentage = slice_config[mod_id]->ul[i]->percentage;
|
||||
config->ul[i]->has_isolation = 1;
|
||||
config->ul[i]->isolation = slice_config[mod_id]->ul[i]->isolation;
|
||||
config->ul[i]->has_priority = 1;
|
||||
config->ul[i]->priority = slice_config[mod_id]->ul[i]->priority;
|
||||
config->ul[i]->has_first_rb = 1;
|
||||
config->ul[i]->first_rb = slice_config[mod_id]->ul[i]->first_rb;
|
||||
config->ul[i]->has_maxmcs = 1;
|
||||
config->ul[i]->maxmcs = slice_config[mod_id]->ul[i]->maxmcs;
|
||||
config->ul[i]->n_sorting = slice_config[mod_id]->ul[i]->n_sorting;
|
||||
config->ul[i]->sorting = calloc(config->ul[i]->n_sorting, sizeof(Protocol__FlexUlSorting));
|
||||
if (!config->ul[i]->sorting) config->ul[i]->n_sorting = 0;
|
||||
for (int j = 0; j < config->ul[i]->n_sorting; ++j)
|
||||
config->ul[i]->sorting[j] = slice_config[mod_id]->ul[i]->sorting[j];
|
||||
config->ul[i]->has_accounting = 1;
|
||||
config->ul[i]->accounting = slice_config[mod_id]->ul[i]->accounting;
|
||||
config->ul[i]->scheduler_name = strdup(slice_config[mod_id]->ul[i]->scheduler_name);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -33,14 +33,6 @@
|
||||
#include "flexran_agent_mac_internal.h"
|
||||
#include "flexran_agent_mac_slice_verification.h"
|
||||
|
||||
/* from flexran_agent_mac.c */
|
||||
extern Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES];
|
||||
extern Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES];
|
||||
extern int perform_slice_config_update_count;
|
||||
extern Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES];
|
||||
extern int n_ue_slice_assoc_updates;
|
||||
extern pthread_mutex_t sc_update_mtx;
|
||||
|
||||
Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message,
|
||||
Protocol__FlexranMessage *old_message) {
|
||||
|
||||
@@ -1033,724 +1025,166 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) {
|
||||
|
||||
}
|
||||
|
||||
Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul)
|
||||
{
|
||||
int i;
|
||||
Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig));
|
||||
if (!fsc) return NULL;
|
||||
protocol__flex_slice_config__init(fsc);
|
||||
|
||||
/* say there are n_dl slices but reserve memory for up to MAX_NUM_SLICES so
|
||||
* we don't need to reserve again later */
|
||||
fsc->n_dl = n_dl;
|
||||
fsc->dl = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexDlSlice *));
|
||||
if (!fsc->dl) fsc->n_dl = 0;
|
||||
for (i = 0; i < MAX_NUM_SLICES; i++) {
|
||||
fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice));
|
||||
if (!fsc->dl[i]) continue;
|
||||
protocol__flex_dl_slice__init(fsc->dl[i]);
|
||||
}
|
||||
|
||||
/* as above */
|
||||
fsc->n_ul = m_ul;
|
||||
fsc->ul = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexUlSlice *));
|
||||
if (!fsc->ul) fsc->n_ul = 0;
|
||||
for (i = 0; i < MAX_NUM_SLICES; i++) {
|
||||
fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice));
|
||||
if (!fsc->ul[i]) continue;
|
||||
protocol__flex_ul_slice__init(fsc->ul[i]);
|
||||
}
|
||||
return fsc;
|
||||
}
|
||||
|
||||
void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s)
|
||||
{
|
||||
s->intraslice_share_active = flexran_get_intraslice_sharing_active(mod_id);
|
||||
s->has_intraslice_share_active = 1;
|
||||
s->interslice_share_active = flexran_get_interslice_sharing_active(mod_id);
|
||||
s->has_interslice_share_active = 1;
|
||||
}
|
||||
|
||||
void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice)
|
||||
{
|
||||
dl_slice->id = flexran_get_dl_slice_id(mod_id, slice_idx);
|
||||
dl_slice->has_id = 1;
|
||||
/* read label from corresponding sc_update entry or give default */
|
||||
dl_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB;
|
||||
dl_slice->has_label = 1;
|
||||
for (int i = 0; i < sc_update[mod_id]->n_dl; i++) {
|
||||
if (sc_update[mod_id]->dl[i]->id == dl_slice->id
|
||||
&& sc_update[mod_id]->dl[i]->has_label) {
|
||||
dl_slice->label = sc_update[mod_id]->dl[i]->label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dl_slice->percentage = flexran_get_dl_slice_percentage(mod_id, slice_idx);
|
||||
dl_slice->has_percentage = 1;
|
||||
dl_slice->isolation = flexran_get_dl_slice_isolation(mod_id, slice_idx);
|
||||
dl_slice->has_isolation = 1;
|
||||
dl_slice->priority = flexran_get_dl_slice_priority(mod_id, slice_idx);
|
||||
dl_slice->has_priority = 1;
|
||||
dl_slice->position_low = flexran_get_dl_slice_position_low(mod_id, slice_idx);
|
||||
dl_slice->has_position_low = 1;
|
||||
dl_slice->position_high = flexran_get_dl_slice_position_high(mod_id, slice_idx);
|
||||
dl_slice->has_position_high = 1;
|
||||
dl_slice->maxmcs = flexran_get_dl_slice_maxmcs(mod_id, slice_idx);
|
||||
dl_slice->has_maxmcs = 1;
|
||||
dl_slice->n_sorting = flexran_get_dl_slice_sorting(mod_id, slice_idx, &dl_slice->sorting);
|
||||
if (dl_slice->n_sorting < 1) dl_slice->sorting = NULL;
|
||||
dl_slice->accounting = flexran_get_dl_slice_accounting_policy(mod_id, slice_idx);
|
||||
dl_slice->has_accounting = 1;
|
||||
const char *s_name = flexran_get_dl_slice_scheduler(mod_id, slice_idx);
|
||||
if (!dl_slice->scheduler_name
|
||||
|| strcmp(dl_slice->scheduler_name, s_name) != 0) {
|
||||
dl_slice->scheduler_name = realloc(dl_slice->scheduler_name, strlen(s_name) + 1);
|
||||
strcpy(dl_slice->scheduler_name, s_name);
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice)
|
||||
{
|
||||
ul_slice->id = flexran_get_ul_slice_id(mod_id, slice_idx);
|
||||
ul_slice->has_id = 1;
|
||||
/* read label from corresponding sc_update entry or give default */
|
||||
ul_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB;
|
||||
ul_slice->has_label = 1;
|
||||
for (int i = 0; i < sc_update[mod_id]->n_ul; i++) {
|
||||
if (sc_update[mod_id]->ul[i]->id == ul_slice->id
|
||||
&& sc_update[mod_id]->ul[i]->has_label) {
|
||||
ul_slice->label = sc_update[mod_id]->ul[i]->label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ul_slice->percentage = flexran_get_ul_slice_percentage(mod_id, slice_idx);
|
||||
ul_slice->has_percentage = 1;
|
||||
/*ul_slice->isolation = flexran_get_ul_slice_isolation(mod_id, slice_idx);*/
|
||||
ul_slice->has_isolation = 0;
|
||||
/*ul_slice->priority = flexran_get_ul_slice_priority(mod_id, slice_idx);*/
|
||||
ul_slice->has_priority = 0;
|
||||
ul_slice->first_rb = flexran_get_ul_slice_first_rb(mod_id, slice_idx);
|
||||
ul_slice->has_first_rb = 1;
|
||||
/*ul_slice-> = flexran_get_ul_slice_length_rb(mod_id, slice_idx);
|
||||
ul_slice->has_length_rb = 0;*/
|
||||
ul_slice->maxmcs = flexran_get_ul_slice_maxmcs(mod_id, slice_idx);
|
||||
ul_slice->has_maxmcs = 1;
|
||||
ul_slice->n_sorting = 0;
|
||||
/*if (ul_slice->sorting) {
|
||||
free(ul_slice->sorting);
|
||||
ul_slice->sorting = NULL;
|
||||
}
|
||||
ul_slice->n_sorting = flexran_get_ul_slice_sorting(mod_id, slice_idx, &ul_slice->sorting);
|
||||
if (ul_slice->n_sorting < 1) ul_slice->sorting = NULL;*/
|
||||
/*ul_slice->accounting = flexran_get_ul_slice_accounting_policy(mod_id, slice_idx);*/
|
||||
ul_slice->has_accounting = 0;
|
||||
const char *s_name = flexran_get_ul_slice_scheduler(mod_id, slice_idx);
|
||||
if (!ul_slice->scheduler_name
|
||||
|| strcmp(ul_slice->scheduler_name, s_name) != 0) {
|
||||
ul_slice->scheduler_name = realloc(ul_slice->scheduler_name, strlen(s_name) + 1);
|
||||
strcpy(ul_slice->scheduler_name, s_name);
|
||||
}
|
||||
}
|
||||
|
||||
int check_dl_sorting_update(Protocol__FlexDlSlice *old, Protocol__FlexDlSlice *new)
|
||||
{
|
||||
/* sorting_update => true when old->n_sorting == 0 or different numbers of
|
||||
* elements; otherwise will check * element-wise */
|
||||
int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting);
|
||||
for (int i = 0; i < old->n_sorting && !sorting_update; ++i) {
|
||||
sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]);
|
||||
}
|
||||
return sorting_update;
|
||||
}
|
||||
|
||||
int check_ul_sorting_update(Protocol__FlexUlSlice *old, Protocol__FlexUlSlice *new)
|
||||
{
|
||||
/* sorting_update => true when old->n_sorting == 0 or different numbers of
|
||||
* elements; otherwise will check * element-wise */
|
||||
int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting);
|
||||
for (int i = 0; i < old->n_sorting && !sorting_update; ++i) {
|
||||
sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]);
|
||||
}
|
||||
return sorting_update;
|
||||
}
|
||||
|
||||
void overwrite_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *exist, Protocol__FlexSliceConfig *update)
|
||||
{
|
||||
if (update->has_intraslice_share_active
|
||||
&& exist->intraslice_share_active != update->intraslice_share_active) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] update intraslice_share_active: %d -> %d\n",
|
||||
mod_id, exist->intraslice_share_active, update->intraslice_share_active);
|
||||
exist->intraslice_share_active = update->intraslice_share_active;
|
||||
exist->has_intraslice_share_active = 1;
|
||||
}
|
||||
if (update->has_interslice_share_active
|
||||
&& exist->interslice_share_active != update->interslice_share_active) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] update interslice_share_active: %d -> %d\n",
|
||||
mod_id, exist->interslice_share_active, update->interslice_share_active);
|
||||
exist->interslice_share_active = update->interslice_share_active;
|
||||
exist->has_interslice_share_active = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void overwrite_slice_config_dl(mid_t mod_id, Protocol__FlexDlSlice *exist, Protocol__FlexDlSlice *update)
|
||||
{
|
||||
if (update->label != exist->label) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update label: %d -> %d\n",
|
||||
mod_id, update->id, exist->label, update->label);
|
||||
exist->label = update->label;
|
||||
exist->has_label = 1;
|
||||
}
|
||||
if (update->percentage != exist->percentage) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update percentage: %d -> %d\n",
|
||||
mod_id, update->id, exist->percentage, update->percentage);
|
||||
exist->percentage = update->percentage;
|
||||
exist->has_percentage = 1;
|
||||
}
|
||||
if (update->isolation != exist->isolation) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update isolation: %d -> %d\n",
|
||||
mod_id, update->id, exist->isolation, update->isolation);
|
||||
exist->isolation = update->isolation;
|
||||
exist->has_isolation = 1;
|
||||
}
|
||||
if (update->priority != exist->priority) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update priority: %d -> %d\n",
|
||||
mod_id, update->id, exist->priority, update->priority);
|
||||
exist->priority = update->priority;
|
||||
exist->has_priority = 1;
|
||||
}
|
||||
if (update->position_low != exist->position_low) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_low: %d -> %d\n",
|
||||
mod_id, update->id, exist->position_low, update->position_low);
|
||||
exist->position_low = update->position_low;
|
||||
exist->has_position_low = 1;
|
||||
}
|
||||
if (update->position_high != exist->position_high) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_high: %d -> %d\n",
|
||||
mod_id, update->id, exist->position_high, update->position_high);
|
||||
exist->position_high = update->position_high;
|
||||
exist->has_position_high = 1;
|
||||
}
|
||||
if (update->maxmcs != exist->maxmcs) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update maxmcs: %d -> %d\n",
|
||||
mod_id, update->id, exist->maxmcs, update->maxmcs);
|
||||
exist->maxmcs = update->maxmcs;
|
||||
exist->has_maxmcs = 1;
|
||||
}
|
||||
if (check_dl_sorting_update(exist, update)) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update sorting array\n", mod_id, update->id);
|
||||
if (exist->n_sorting != update->n_sorting) {
|
||||
exist->n_sorting = update->n_sorting;
|
||||
exist->sorting = realloc(exist->sorting, exist->n_sorting * sizeof(Protocol__FlexDlSorting));
|
||||
if (!exist->sorting) exist->n_sorting = 0;
|
||||
}
|
||||
for (int i = 0; i < exist->n_sorting; i++)
|
||||
exist->sorting[i] = update->sorting[i];
|
||||
}
|
||||
if (update->accounting != exist->accounting) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update accounting: %d -> %d\n",
|
||||
mod_id, update->id, exist->accounting, update->accounting);
|
||||
exist->accounting = update->accounting;
|
||||
exist->has_accounting = 1;
|
||||
}
|
||||
if (!exist->scheduler_name
|
||||
|| strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update scheduler: %s -> %s\n",
|
||||
mod_id, update->id, exist->scheduler_name, update->scheduler_name);
|
||||
if (exist->scheduler_name) free(exist->scheduler_name);
|
||||
exist->scheduler_name = strdup(update->scheduler_name);
|
||||
}
|
||||
}
|
||||
|
||||
void overwrite_slice_config_ul(mid_t mod_id, Protocol__FlexUlSlice *exist, Protocol__FlexUlSlice *update)
|
||||
{
|
||||
if (update->label != exist->label) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update label: %d -> %d\n",
|
||||
mod_id, update->id, exist->label, update->label);
|
||||
exist->label = update->label;
|
||||
exist->has_label = 1;
|
||||
}
|
||||
if (update->percentage != exist->percentage) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update percentage: %d -> %d\n",
|
||||
mod_id, update->id, exist->percentage, update->percentage);
|
||||
exist->percentage = update->percentage;
|
||||
exist->has_percentage = 1;
|
||||
}
|
||||
if (update->isolation != exist->isolation) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update isolation: %d -> %d\n",
|
||||
mod_id, update->id, exist->isolation, update->isolation);
|
||||
exist->isolation = update->isolation;
|
||||
exist->has_isolation = 1;
|
||||
}
|
||||
if (update->priority != exist->priority) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update priority: %d -> %d\n",
|
||||
mod_id, update->id, exist->priority, update->priority);
|
||||
exist->priority = update->priority;
|
||||
exist->has_priority = 1;
|
||||
}
|
||||
if (update->first_rb != exist->first_rb) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update first_rb: %d -> %d\n",
|
||||
mod_id, update->id, exist->first_rb, update->first_rb);
|
||||
exist->first_rb = update ->first_rb;
|
||||
exist->has_first_rb = 1;
|
||||
}
|
||||
/*if (update->lenght_rb != exist->lenght_rb) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update lenght_rb: %d -> %d\n",
|
||||
mod_id, update->id, exist->lenght_rb, update->lenght_rb);
|
||||
exist->lenght_rb = update->lenght_rb;
|
||||
}*/
|
||||
if (update->maxmcs != exist->maxmcs) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update maxmcs: %d -> %d\n",
|
||||
mod_id, update->id, exist->maxmcs, update->maxmcs);
|
||||
exist->maxmcs = update->maxmcs;
|
||||
exist->has_maxmcs = 1;
|
||||
}
|
||||
/* TODO
|
||||
int sorting_update = 0;
|
||||
int n = min(exist->n_sorting, update->n_sorting);
|
||||
int i = 0;
|
||||
while (i < n && !sorting_update) {
|
||||
sorting_update = sorting_update || (update->sorting[i] != exist->sorting[i]);
|
||||
i++;
|
||||
}
|
||||
if (sorting_update) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update sorting array\n", update->id, mod_id);
|
||||
if (exist->n_sorting != update->n_sorting)
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] only writing %d elements\n",
|
||||
mod_id, update->id, n);
|
||||
for (i = 0; i < n; i++)
|
||||
exist->sorting[i] = update->sorting[i];
|
||||
}
|
||||
*/
|
||||
if (update->accounting != exist->accounting) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update accounting: %d -> %d\n",
|
||||
mod_id, update->id, exist->accounting, update->accounting);
|
||||
exist->accounting = update->accounting;
|
||||
exist->has_accounting = 1;
|
||||
}
|
||||
if (!exist->scheduler_name
|
||||
|| strcmp(update->scheduler_name, exist->scheduler_name) != 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update scheduler: %s -> %s\n",
|
||||
mod_id, update->id, exist->scheduler_name, update->scheduler_name);
|
||||
if (exist->scheduler_name) free(exist->scheduler_name);
|
||||
exist->scheduler_name = strdup(update->scheduler_name);
|
||||
}
|
||||
}
|
||||
|
||||
void fill_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *s, Protocol__FlexDlSlice *from)
|
||||
{
|
||||
/* function fills slice with information from another slice or with default
|
||||
* values (currently slice 0) if from is NULL */
|
||||
/* TODO fill the slice depending on the chosen label */
|
||||
if (!s->has_label) {
|
||||
s->has_label = 1;
|
||||
s->label = from ? from->label : sc_update[mod_id]->dl[0]->label;
|
||||
}
|
||||
if (!s->has_percentage) {
|
||||
s->has_percentage = 1;
|
||||
s->percentage = from ? from->percentage : sc_update[mod_id]->dl[0]->percentage;
|
||||
}
|
||||
if (!s->has_isolation) {
|
||||
s->has_isolation = 1;
|
||||
s->isolation = from ? from->isolation : sc_update[mod_id]->dl[0]->isolation;
|
||||
}
|
||||
if (!s->has_priority) {
|
||||
s->has_priority = 1;
|
||||
s->priority = from ? from->priority : sc_update[mod_id]->dl[0]->priority;
|
||||
}
|
||||
if (!s->has_position_low) {
|
||||
s->has_position_low = 1;
|
||||
s->position_low = from ? from->position_low : sc_update[mod_id]->dl[0]->position_low;
|
||||
}
|
||||
if (!s->has_position_high) {
|
||||
s->has_position_high = 1;
|
||||
s->position_high = from ? from->position_high : sc_update[mod_id]->dl[0]->position_high;
|
||||
}
|
||||
if (!s->has_maxmcs) {
|
||||
s->has_maxmcs = 1;
|
||||
s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->dl[0]->maxmcs;
|
||||
}
|
||||
if (s->n_sorting == 0) {
|
||||
s->n_sorting = from ? from->n_sorting : sc_update[mod_id]->dl[0]->n_sorting;
|
||||
s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexDlSorting));
|
||||
if (!s->sorting) s->n_sorting = 0;
|
||||
for (int i = 0; i < s->n_sorting; ++i)
|
||||
s->sorting[i] = from ? from->sorting[i] : sc_update[0]->dl[0]->sorting[i];
|
||||
}
|
||||
if (!s->has_accounting) {
|
||||
s->accounting = from ? from->accounting : sc_update[mod_id]->dl[0]->accounting;
|
||||
}
|
||||
if (!s->scheduler_name) {
|
||||
s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->dl[0]->scheduler_name);
|
||||
}
|
||||
}
|
||||
|
||||
Protocol__FlexDlSlice *get_existing_dl_slice(mid_t mod_id, int id)
|
||||
{
|
||||
for (int i = 0; i < sc_update[mod_id]->n_dl; ++i) {
|
||||
if (id == sc_update[mod_id]->dl[i]->id) {
|
||||
return sc_update[mod_id]->dl[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id)
|
||||
{
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"[%d] Creating DL slice with ID %d, taking default values from DL slice 0\n",
|
||||
mod_id, id);
|
||||
Protocol__FlexDlSlice *to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl];
|
||||
sc_update[mod_id]->n_dl++;
|
||||
AssertFatal(sc_update[mod_id]->n_dl <= MAX_NUM_SLICES,
|
||||
"cannot create more than MAX_NUM_SLICES\n");
|
||||
to->id = id;
|
||||
return to;
|
||||
}
|
||||
|
||||
void fill_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *s, Protocol__FlexUlSlice *from)
|
||||
{
|
||||
/* function fills slice with information from another slice or with default
|
||||
* values (currently slice 0) if from is NULL */
|
||||
/* TODO fill the slice depending on the chosen label */
|
||||
if (!s->has_label) {
|
||||
s->has_label = 1;
|
||||
s->label = from ? from->label : sc_update[mod_id]->ul[0]->label;
|
||||
}
|
||||
if (!s->has_percentage) {
|
||||
s->has_percentage = 1;
|
||||
s->percentage = from ? from->percentage : sc_update[mod_id]->ul[0]->percentage;
|
||||
}
|
||||
if (!s->has_isolation) {
|
||||
s->has_isolation = 1;
|
||||
s->isolation = from ? from->isolation : sc_update[mod_id]->ul[0]->isolation;
|
||||
}
|
||||
if (!s->has_priority) {
|
||||
s->has_priority = 1;
|
||||
s->priority = from ? from->priority : sc_update[mod_id]->ul[0]->priority;
|
||||
}
|
||||
if (!s->has_first_rb) {
|
||||
s->has_first_rb = 1;
|
||||
s->first_rb = from ? from->first_rb : sc_update[mod_id]->ul[0]->first_rb;
|
||||
}
|
||||
if (!s->has_maxmcs) {
|
||||
s->has_maxmcs = 1;
|
||||
s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->ul[0]->maxmcs;
|
||||
}
|
||||
if (s->n_sorting == 0) {
|
||||
s->n_sorting = from ? from->n_sorting : sc_update[0]->ul[0]->n_sorting;
|
||||
s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexUlSorting));
|
||||
if (!s->sorting) s->n_sorting = 0;
|
||||
for (int i = 0; i < s->n_sorting; ++i)
|
||||
s->sorting[i] = from ? from->sorting[i] : sc_update[0]->ul[0]->sorting[i];
|
||||
}
|
||||
if (!s->has_accounting) {
|
||||
s->accounting = from ? from->accounting : sc_update[0]->ul[0]->accounting;
|
||||
}
|
||||
if (!s->scheduler_name) {
|
||||
s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->ul[0]->scheduler_name);
|
||||
}
|
||||
}
|
||||
|
||||
Protocol__FlexUlSlice *get_existing_ul_slice(mid_t mod_id, int id)
|
||||
{
|
||||
for (int i = 0; i < sc_update[mod_id]->n_ul; ++i) {
|
||||
if (id == sc_update[mod_id]->ul[i]->id) {
|
||||
return sc_update[mod_id]->ul[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Protocol__FlexUlSlice *create_new_ul_slice(mid_t mod_id, int id)
|
||||
{
|
||||
LOG_I(FLEXRAN_AGENT,
|
||||
"[%d] Creating UL slice with ID %d, taking default values from UL slice 0\n",
|
||||
mod_id, id);
|
||||
Protocol__FlexUlSlice *to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul];
|
||||
sc_update[mod_id]->n_ul++;
|
||||
AssertFatal(sc_update[mod_id]->n_ul <= MAX_NUM_SLICES,
|
||||
"cannot create more than MAX_NUM_SLICES\n");
|
||||
to->id = id;
|
||||
return to;
|
||||
}
|
||||
|
||||
void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *sup)
|
||||
{
|
||||
int verified = 1;
|
||||
if (!sc_update[mod_id]) {
|
||||
LOG_E(FLEXRAN_AGENT, "Can not update slice policy (no existing slice profile)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&sc_update_mtx);
|
||||
/* no need for tests in the current state as there are only two protobuf
|
||||
* bools for intra-/interslice sharing. The function applies new values if
|
||||
* applicable */
|
||||
overwrite_slice_config(mod_id, sc_update[mod_id], sup);
|
||||
|
||||
if (sup->n_dl == 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] no DL slice configuration in flex_slice_config message\n", mod_id);
|
||||
void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) {
|
||||
if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET
|
||||
&& !s->label && !s->scheduler) {
|
||||
LOG_I(FLEXRAN_AGENT, "remove DL slice ID %d\n", s->id);
|
||||
const int rc = flexran_remove_dl_slice(mod_id, s);
|
||||
if (!rc)
|
||||
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
|
||||
} else {
|
||||
/* verify slice parameters */
|
||||
for (int i = 0; i < sup->n_dl; i++) {
|
||||
if (!sup->dl[i]->has_id) {
|
||||
verified = 0;
|
||||
break;
|
||||
}
|
||||
Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id);
|
||||
/* fill up so that the slice is complete. This way, we don't need to
|
||||
* worry about it later */
|
||||
fill_dl_slice(mod_id, sup->dl[i], dls);
|
||||
verified = verified && flexran_verify_dl_slice(mod_id, sup->dl[i]);
|
||||
if (!verified) break;
|
||||
}
|
||||
|
||||
/* verify group-based parameters (e.g. sum percentage should not exceed
|
||||
* 100%). Can be used to perform admission control */
|
||||
verified = verified && flexran_verify_group_dl_slices(mod_id,
|
||||
sc_update[mod_id]->dl, sc_update[mod_id]->n_dl, sup->dl, sup->n_dl);
|
||||
|
||||
if (verified) {
|
||||
for (int i = 0; i < sup->n_dl; i++) {
|
||||
/* if all verifications were successful, get existing slice for ID or
|
||||
* create new one and overwrite with the update */
|
||||
Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id);
|
||||
if (!dls) dls = create_new_dl_slice(mod_id, sup->dl[i]->id);
|
||||
overwrite_slice_config_dl(mod_id, dls, sup->dl[i]);
|
||||
}
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] DL slice verification failed, refusing application\n", mod_id);
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id);
|
||||
const int rc = flexran_create_dl_slice(mod_id, s);
|
||||
if (rc < 0)
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"error while update slice ID %d: flexran_create_dl_slice() -> %d\n",
|
||||
s->id, rc);
|
||||
}
|
||||
}
|
||||
|
||||
verified = 1;
|
||||
if (sup->n_ul == 0) {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_id);
|
||||
void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) {
|
||||
if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET
|
||||
&& !s->label && !s->scheduler) {
|
||||
LOG_I(FLEXRAN_AGENT, "remove UL slice ID %d\n", s->id);
|
||||
const int rc = flexran_remove_ul_slice(mod_id, s);
|
||||
if (!rc)
|
||||
LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id);
|
||||
} else {
|
||||
/* verify slice parameters */
|
||||
for (int i = 0; i < sup->n_ul; i++) {
|
||||
if (!sup->ul[i]->has_id) {
|
||||
verified = 0;
|
||||
break;
|
||||
}
|
||||
Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id);
|
||||
/* fill up so that the slice is complete. This way, we don't need to
|
||||
* worry about it later */
|
||||
fill_ul_slice(mod_id, sup->ul[i], uls);
|
||||
verified = verified && flexran_verify_ul_slice(mod_id, sup->ul[i]);
|
||||
if (!verified) break;
|
||||
}
|
||||
|
||||
/* verify group-based parameters (e.g. sum percentage should not exceed
|
||||
* 100%). Can be used to perform admission control */
|
||||
verified = verified && flexran_verify_group_ul_slices(mod_id,
|
||||
sc_update[mod_id]->ul, sc_update[mod_id]->n_ul, sup->ul, sup->n_ul);
|
||||
|
||||
if (verified) {
|
||||
for (int i = 0; i < sup->n_ul; i++) {
|
||||
/* if all verifications were successful, get existing slice for ID or
|
||||
* create new one and overwrite with the update */
|
||||
Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id);
|
||||
if (!uls) uls = create_new_ul_slice(mod_id, sup->ul[i]->id);
|
||||
overwrite_slice_config_ul(mod_id, uls, sup->ul[i]);
|
||||
}
|
||||
} else {
|
||||
LOG_E(FLEXRAN_AGENT, "[%d] UL slice verification failed, refusing application\n", mod_id);
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id);
|
||||
const int rc = flexran_create_ul_slice(mod_id, s);
|
||||
if (rc < 0)
|
||||
LOG_W(FLEXRAN_AGENT,
|
||||
"error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n",
|
||||
s->id, rc);
|
||||
}
|
||||
pthread_mutex_unlock(&sc_update_mtx);
|
||||
|
||||
perform_slice_config_update_count = 1;
|
||||
}
|
||||
|
||||
int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news)
|
||||
{
|
||||
/* not setting the old configuration is intentional, as it will be picked up
|
||||
* later when reading the configuration. There is thus a direct feedback
|
||||
* whether it has been set. */
|
||||
int changes = 0;
|
||||
if (olds->intraslice_share_active != news->intraslice_share_active) {
|
||||
flexran_set_intraslice_sharing_active(mod_id, news->intraslice_share_active);
|
||||
changes++;
|
||||
}
|
||||
if (olds->interslice_share_active != news->interslice_share_active) {
|
||||
flexran_set_interslice_sharing_active(mod_id, news->interslice_share_active);
|
||||
changes++;
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc)
|
||||
{
|
||||
/* not setting the old configuration is intentional, as it will be picked up
|
||||
* later when reading the configuration. There is thus a direct feedback
|
||||
* whether it has been set. */
|
||||
int changes = 0;
|
||||
int slice_idx = flexran_find_dl_slice(mod_id, newc->id);
|
||||
if (slice_idx < 0) {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id);
|
||||
return 0;
|
||||
}
|
||||
if (oldc->percentage != newc->percentage) {
|
||||
flexran_set_dl_slice_percentage(mod_id, slice_idx, newc->percentage);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->isolation != newc->isolation) {
|
||||
flexran_set_dl_slice_isolation(mod_id, slice_idx, newc->isolation);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->priority != newc->priority) {
|
||||
flexran_set_dl_slice_priority(mod_id, slice_idx, newc->priority);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->position_low != newc->position_low) {
|
||||
flexran_set_dl_slice_position_low(mod_id, slice_idx, newc->position_low);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->position_high != newc->position_high) {
|
||||
flexran_set_dl_slice_position_high(mod_id, slice_idx, newc->position_high);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->maxmcs != newc->maxmcs) {
|
||||
flexran_set_dl_slice_maxmcs(mod_id, slice_idx, newc->maxmcs);
|
||||
changes++;
|
||||
}
|
||||
if (check_dl_sorting_update(oldc, newc)) {
|
||||
flexran_set_dl_slice_sorting(mod_id, slice_idx, newc->sorting, newc->n_sorting);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->accounting != newc->accounting) {
|
||||
flexran_set_dl_slice_accounting_policy(mod_id, slice_idx, newc->accounting);
|
||||
changes++;
|
||||
}
|
||||
if (!oldc->scheduler_name
|
||||
|| strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
|
||||
int ret = flexran_set_dl_slice_scheduler(mod_id, slice_idx, newc->scheduler_name);
|
||||
AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n",
|
||||
newc->id, slice_idx);
|
||||
changes++;
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc)
|
||||
{
|
||||
/* not setting the old configuration is intentional, as it will be picked up
|
||||
* later when reading the configuration. There is thus a direct feedback
|
||||
* whether it has been set. */
|
||||
int changes = 0;
|
||||
int slice_idx = flexran_find_ul_slice(mod_id, newc->id);
|
||||
if (slice_idx < 0) {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id);
|
||||
return 0;
|
||||
}
|
||||
if (oldc->percentage != newc->percentage) {
|
||||
flexran_set_ul_slice_percentage(mod_id, slice_idx, newc->percentage);
|
||||
changes++;
|
||||
}
|
||||
if (oldc->isolation != newc->isolation) {
|
||||
/*flexran_set_ul_slice_isolation(mod_id, slice_idx, newc->isolation);
|
||||
*changes++;*/
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting isolation is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}
|
||||
if (oldc->priority != newc->priority) {
|
||||
/*flexran_set_ul_slice_priority(mod_id, slice_idx, newc->priority);
|
||||
*changes++;*/
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the priority is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}
|
||||
if (oldc->first_rb != newc->first_rb) {
|
||||
flexran_set_ul_slice_first_rb(mod_id, slice_idx, newc->first_rb);
|
||||
changes++;
|
||||
}
|
||||
/*if (oldc->length_rb != newc->length_rb) {
|
||||
flexran_set_ul_slice_length_rb(mod_id, slice_idx, newc->length_rb);
|
||||
changes++;
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting length_rb is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}*/
|
||||
if (oldc->maxmcs != newc->maxmcs) {
|
||||
flexran_set_ul_slice_maxmcs(mod_id, slice_idx, newc->maxmcs);
|
||||
changes++;
|
||||
}
|
||||
/*if (check_ul_sorting_update(oldc, newc)) {
|
||||
flexran_set_ul_slice_sorting(mod_id, slice_idx, newc->sorting, n);
|
||||
changes++;
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the sorting is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}*/
|
||||
if (oldc->accounting != newc->accounting) {
|
||||
/*flexran_set_ul_slice_accounting_policy(mod_id, slice_idx, newc->accounting);
|
||||
*changes++;*/
|
||||
LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the accounting is not supported\n",
|
||||
mod_id, newc->id);
|
||||
}
|
||||
if (!oldc->scheduler_name
|
||||
|| strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) {
|
||||
int ret = flexran_set_ul_slice_scheduler(mod_id, slice_idx, newc->scheduler_name);
|
||||
AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n",
|
||||
newc->id, slice_idx);
|
||||
changes++;
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config)
|
||||
{
|
||||
if (n_ue_slice_assoc_updates == MAX_NUM_SLICES) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"[%d] can not handle flex_ue_config message, buffer is full; try again later\n",
|
||||
mod_id);
|
||||
void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *dl) {
|
||||
if (!dl)
|
||||
return;
|
||||
|
||||
Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id);
|
||||
if (dl->has_algorithm && dl_algo != dl->algorithm) {
|
||||
LOG_I(FLEXRAN_AGENT, "loading new DL slice algorithm %d\n", dl->algorithm);
|
||||
dl_algo = dl->algorithm;
|
||||
flexran_set_dl_slice_algo(mod_id, dl_algo);
|
||||
}
|
||||
|
||||
/* first update existing slices, then create new. Thus, we go through the
|
||||
* list twice. First round, if a slice exists, handle and mark as such. Then,
|
||||
* apply all others in the second round */
|
||||
if (dl->n_slices > 0) {
|
||||
if (dl_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
int handled_dl[dl->n_slices];
|
||||
for (int i = 0; i < dl->n_slices; ++i) {
|
||||
if (flexran_find_dl_slice(mod_id, dl->slices[i]->id) < 0) {
|
||||
handled_dl[i] = 0;
|
||||
continue;
|
||||
}
|
||||
update_or_remove_dl(mod_id, dl->slices[i]);
|
||||
handled_dl[i] = 1;
|
||||
}
|
||||
for (int i = 0; i < dl->n_slices; ++i) {
|
||||
if (handled_dl[i])
|
||||
continue;
|
||||
update_or_remove_dl(mod_id, dl->slices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (dl->scheduler) {
|
||||
if (dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler);
|
||||
const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"error while updating scheduling algorithm: "
|
||||
"flexran_update_dl_sched_algo() -> %d)\n",
|
||||
rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *ul) {
|
||||
if (!ul)
|
||||
return;
|
||||
|
||||
Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id);
|
||||
if (ul->has_algorithm && ul_algo != ul->algorithm) {
|
||||
LOG_I(FLEXRAN_AGENT, "loading new UL slice algorithm %d\n", ul->algorithm);
|
||||
ul_algo = ul->algorithm;
|
||||
flexran_set_ul_slice_algo(mod_id, ul_algo);
|
||||
}
|
||||
if (ul->n_slices > 0) {
|
||||
if (ul_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
int handled_ul[ul->n_slices];
|
||||
for (int i = 0; i < ul->n_slices; ++i) {
|
||||
if (flexran_find_ul_slice(mod_id, ul->slices[i]->id) < 0) {
|
||||
handled_ul[i] = 0;
|
||||
continue;
|
||||
}
|
||||
update_or_remove_ul(mod_id, ul->slices[i]);
|
||||
handled_ul[i] = 1;
|
||||
}
|
||||
for (int i = 0; i < ul->n_slices; ++i) {
|
||||
if (handled_ul[i])
|
||||
continue;
|
||||
update_or_remove_ul(mod_id, ul->slices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ul->scheduler) {
|
||||
if (ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n");
|
||||
return;
|
||||
}
|
||||
LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler);
|
||||
const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler);
|
||||
if (rc < 0) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"error while updating scheduling algorithm: "
|
||||
"flexran_update_dl_sched_algo() -> %d)\n",
|
||||
rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config)
|
||||
{
|
||||
if (!ue_config->has_rnti) {
|
||||
LOG_E(FLEXRAN_AGENT,
|
||||
"[%d] cannot update UE to slice association, no RNTI in flex_ue_config message\n",
|
||||
mod_id);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (ue_config->has_dl_slice_id)
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to DL slice ID %d\n",
|
||||
mod_id, ue_config->rnti, ue_config->dl_slice_id);
|
||||
if (ue_config->has_ul_slice_id)
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to UL slice ID %d\n",
|
||||
mod_id, ue_config->rnti, ue_config->ul_slice_id);
|
||||
ue_slice_assoc_update[n_ue_slice_assoc_updates++] = ue_config;
|
||||
perform_slice_config_update_count = 2;
|
||||
}
|
||||
|
||||
int apply_ue_slice_assoc_update(mid_t mod_id)
|
||||
{
|
||||
int i;
|
||||
int changes = 0;
|
||||
for (i = 0; i < n_ue_slice_assoc_updates; i++) {
|
||||
int ue_id = find_UE_id(mod_id, ue_slice_assoc_update[i]->rnti);
|
||||
if (ue_id < 0 || ue_id > MAX_MOBILES_PER_ENB){
|
||||
LOG_E(FLEXRAN_AGENT,"UE_id %d is wrong!!\n",ue_id);
|
||||
continue;
|
||||
}
|
||||
if (ue_slice_assoc_update[i]->has_dl_slice_id) {
|
||||
int slice_idx = flexran_find_dl_slice(mod_id, ue_slice_assoc_update[i]->dl_slice_id);
|
||||
if (flexran_dl_slice_exists(mod_id, slice_idx)) {
|
||||
flexran_set_ue_dl_slice_idx(mod_id, ue_id, slice_idx);
|
||||
changes++;
|
||||
} else {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] DL slice %d does not exist, refusing change\n",
|
||||
mod_id, ue_slice_assoc_update[i]->dl_slice_id);
|
||||
}
|
||||
}
|
||||
if (ue_slice_assoc_update[i]->has_ul_slice_id) {
|
||||
int slice_idx = flexran_find_ul_slice(mod_id, ue_slice_assoc_update[i]->ul_slice_id);
|
||||
if (flexran_ul_slice_exists(mod_id, slice_idx)) {
|
||||
flexran_set_ue_ul_slice_idx(mod_id, ue_id, slice_idx);
|
||||
changes++;
|
||||
} else {
|
||||
LOG_W(FLEXRAN_AGENT, "[%d] UL slice %d does not exist, refusing change\n",
|
||||
mod_id, ue_slice_assoc_update[i]->ul_slice_id);
|
||||
}
|
||||
int UE_id = flexran_get_mac_ue_id_rnti(mod_id, ue_config->rnti);
|
||||
if (ue_config->has_dl_slice_id) {
|
||||
if (flexran_get_dl_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "no DL slice algorithm loaded\n");
|
||||
} else {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to DL slice ID %d\n",
|
||||
mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->dl_slice_id);
|
||||
flexran_set_ue_dl_slice_id(mod_id, UE_id, ue_config->dl_slice_id);
|
||||
}
|
||||
}
|
||||
n_ue_slice_assoc_updates = 0;
|
||||
return changes;
|
||||
if (ue_config->has_ul_slice_id) {
|
||||
if (flexran_get_ul_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) {
|
||||
LOG_E(FLEXRAN_AGENT, "no UL slice algorithm loaded\n");
|
||||
} else {
|
||||
LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to UL slice ID %d\n",
|
||||
mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->ul_slice_id);
|
||||
flexran_set_ue_ul_slice_id(mod_id, UE_id, ue_config->ul_slice_id);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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_*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -61,82 +61,30 @@ enum flex_qam {
|
||||
//
|
||||
// Slice config related structures and enums
|
||||
//
|
||||
enum flex_dl_sorting {
|
||||
|
||||
CR_ROUND = 0; // Highest HARQ first
|
||||
CR_SRB12 = 1; // Highest SRB1+2 first
|
||||
CR_HOL = 2; // Highest HOL first
|
||||
CR_LC = 3; // Greatest RLC buffer first
|
||||
CR_CQI = 4; // Highest CQI first
|
||||
CR_LCP = 5; // Highest LC priority first
|
||||
enum flex_slice_algorithm {
|
||||
None = 0;
|
||||
Static = 1;
|
||||
NVS = 2;
|
||||
}
|
||||
|
||||
enum flex_ul_sorting {
|
||||
CRU_ROUND = 0; // Highest HARQ first
|
||||
CRU_BUF = 1; // Highest BSR first
|
||||
CRU_BTS = 2; // More bytes to schedule first
|
||||
CRU_MCS = 3; // Highest MCS first
|
||||
CRU_LCP = 4; // Highest LC priority first
|
||||
CRU_HOL = 5; // Highest HOL first
|
||||
message flex_slice_static {
|
||||
optional uint32 posLow = 1;
|
||||
optional uint32 posHigh = 2;
|
||||
}
|
||||
|
||||
enum flex_dl_accounting_policy {
|
||||
POL_FAIR = 0;
|
||||
POL_GREEDY = 1;
|
||||
POL_NUM = 2;
|
||||
message flex_slice {
|
||||
optional uint32 id = 1;
|
||||
optional string label = 2;
|
||||
optional string scheduler = 3;
|
||||
oneof params {
|
||||
flex_slice_static static = 10;
|
||||
}
|
||||
}
|
||||
|
||||
enum flex_ul_accounting_policy {
|
||||
POLU_FAIR = 0;
|
||||
POLU_GREEDY = 1;
|
||||
POLU_NUM = 2;
|
||||
}
|
||||
|
||||
enum flex_slice_label {
|
||||
xMBB = 0;
|
||||
URLLC = 1;
|
||||
mMTC = 2;
|
||||
xMTC = 3;
|
||||
Other = 4;
|
||||
}
|
||||
|
||||
message flex_dl_slice {
|
||||
optional uint32 id = 1;
|
||||
optional flex_slice_label label = 2;
|
||||
// should be between 0 and 100
|
||||
optional uint32 percentage = 3;
|
||||
// whether this slice should be exempted form interslice sharing
|
||||
optional bool isolation = 4;
|
||||
// increasing value means increasing prio
|
||||
optional uint32 priority = 5;
|
||||
// min and max RB to use (in frequency) in the range [0, N_RBG_MAX]
|
||||
optional uint32 position_low = 6;
|
||||
optional uint32 position_high = 7;
|
||||
// maximum MCS to be allowed in this slice
|
||||
optional uint32 maxmcs = 8;
|
||||
repeated flex_dl_sorting sorting = 9;
|
||||
optional flex_dl_accounting_policy accounting = 10;
|
||||
optional string scheduler_name = 11;
|
||||
}
|
||||
|
||||
message flex_ul_slice {
|
||||
optional uint32 id = 1;
|
||||
optional flex_slice_label label = 2;
|
||||
// should be between 0 and 100
|
||||
optional uint32 percentage = 3;
|
||||
// whether this slice should be exempted form interslice sharing
|
||||
optional bool isolation = 4;
|
||||
// increasing value means increasing prio
|
||||
optional uint32 priority = 5;
|
||||
// RB start to use (in frequency) in the range [0, N_RB_MAX]
|
||||
optional uint32 first_rb = 6;
|
||||
// TODO RB number
|
||||
//optional uint32 length_rb = 7;
|
||||
// maximum MCS to be allowed in this slice
|
||||
optional uint32 maxmcs = 8;
|
||||
repeated flex_ul_sorting sorting = 9;
|
||||
optional flex_ul_accounting_policy accounting = 10;
|
||||
optional string scheduler_name = 11;
|
||||
message flex_slice_dl_ul_config {
|
||||
optional flex_slice_algorithm algorithm = 1;
|
||||
repeated flex_slice slices = 2;
|
||||
optional string scheduler = 3; // if no slicing
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "flexran_agent_ran_api.h"
|
||||
#include "s1ap_eNB_ue_context.h"
|
||||
#include "s1ap_eNB_management_procedures.h"
|
||||
#include "openair2/LAYER2/MAC/slicing/slicing.h"
|
||||
|
||||
static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) {
|
||||
return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id];
|
||||
@@ -3013,471 +3014,293 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti)
|
||||
}
|
||||
|
||||
/**************************** SLICING ****************************/
|
||||
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
|
||||
|
||||
int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id];
|
||||
|
||||
if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl)
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
|
||||
|
||||
return 0;
|
||||
switch (RC.mac[mod_id]->pre_processor_dl.algorithm) {
|
||||
case STATIC_SLICING:
|
||||
return PROTOCOL__FLEX_SLICE_ALGORITHM__Static;
|
||||
default:
|
||||
return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
|
||||
}
|
||||
}
|
||||
|
||||
void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) {
|
||||
int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
eNB_MAC_INST *mac = RC.mac[mod_id];
|
||||
const int cc_id = 0;
|
||||
|
||||
pp_impl_param_t dl = mac->pre_processor_dl;
|
||||
switch (algo) {
|
||||
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
|
||||
mac->pre_processor_dl = static_dl_init(mod_id, cc_id);
|
||||
break;
|
||||
default:
|
||||
mac->pre_processor_dl.algorithm = 0;
|
||||
mac->pre_processor_dl.dl = dlsch_scheduler_pre_processor;
|
||||
mac->pre_processor_dl.dl_algo.data = mac->pre_processor_dl.dl_algo.setup();
|
||||
mac->pre_processor_dl.slices = NULL;
|
||||
break;
|
||||
}
|
||||
if (dl.slices)
|
||||
dl.destroy(&dl.slices);
|
||||
if (dl.dl_algo.data)
|
||||
dl.dl_algo.unset(&dl.dl_algo.data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
|
||||
|
||||
switch (RC.mac[mod_id]->pre_processor_ul.algorithm) {
|
||||
case STATIC_SLICING:
|
||||
return PROTOCOL__FLEX_SLICE_ALGORITHM__Static;
|
||||
default:
|
||||
return PROTOCOL__FLEX_SLICE_ALGORITHM__None;
|
||||
}
|
||||
}
|
||||
|
||||
int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
eNB_MAC_INST *mac = RC.mac[mod_id];
|
||||
const int cc_id = 0;
|
||||
|
||||
pp_impl_param_t ul = mac->pre_processor_ul;
|
||||
switch (algo) {
|
||||
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
|
||||
mac->pre_processor_ul = static_ul_init(mod_id, cc_id);
|
||||
break;
|
||||
default:
|
||||
mac->pre_processor_ul.algorithm = 0;
|
||||
mac->pre_processor_ul.ul = ulsch_scheduler_pre_processor;
|
||||
mac->pre_processor_ul.ul_algo.data = mac->pre_processor_ul.ul_algo.setup();
|
||||
mac->pre_processor_ul.slices = NULL;
|
||||
break;
|
||||
}
|
||||
if (ul.slices)
|
||||
ul.destroy(&ul.slices);
|
||||
if (ul.ul_algo.data)
|
||||
ul.ul_algo.unset(&ul.ul_algo.data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
slice_info_t *slices = RC.mac[mod_id]->pre_processor_dl.slices;
|
||||
if (!slices) return -1;
|
||||
const int idx = slices->UE_assoc_slice[ue_id];
|
||||
return slices->s[idx]->id;
|
||||
}
|
||||
|
||||
void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
|
||||
|
||||
if (!flexran_dl_slice_exists(mod_id, slice_idx)) return;
|
||||
|
||||
//RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id] = slice_idx;
|
||||
int idx = flexran_find_dl_slice(mod_id, slice_id);
|
||||
if (idx < 0) return;
|
||||
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
|
||||
dl->move_UE(dl->slices, ue_id, idx);
|
||||
}
|
||||
|
||||
int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id];
|
||||
|
||||
if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul)
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
|
||||
|
||||
return 0;
|
||||
slice_info_t *slices = RC.mac[mod_id]->pre_processor_ul.slices;
|
||||
if (!slices) return -1;
|
||||
const int idx = slices->UE_assoc_slice[ue_id];
|
||||
return slices->s[idx]->id;
|
||||
}
|
||||
|
||||
void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) {
|
||||
void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return;
|
||||
|
||||
if (!flexran_ul_slice_exists(mod_id, slice_idx)) return;
|
||||
|
||||
//RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx;
|
||||
int idx = flexran_find_ul_slice(mod_id, slice_id);
|
||||
if (idx < 0) return;
|
||||
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
|
||||
ul->move_UE(ul->slices, ue_id, idx);
|
||||
}
|
||||
|
||||
int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl;
|
||||
int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
void *params = NULL;
|
||||
switch (s->params_case) {
|
||||
case PROTOCOL__FLEX_SLICE__PARAMS_STATIC:
|
||||
params = malloc(sizeof(static_slice_param_t));
|
||||
if (!params) return 0;
|
||||
((static_slice_param_t *)params)->posLow = s->static_->poslow;
|
||||
((static_slice_param_t *)params)->posHigh = s->static_->poshigh;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
|
||||
char *l = s->label ? strdup(s->label) : NULL;
|
||||
void *algo = &dl->dl_algo; // default scheduler
|
||||
if (s->scheduler) {
|
||||
algo = dlsym(NULL, s->scheduler);
|
||||
if (!algo) {
|
||||
free(params);
|
||||
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
|
||||
return -15;
|
||||
}
|
||||
}
|
||||
return dl->addmod_slice(dl->slices, s->id, l, algo, params);
|
||||
}
|
||||
|
||||
int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
int newidx = RC.mac[mod_id]->slice_info.n_dl;
|
||||
|
||||
if (newidx >= MAX_NUM_SLICES) return -1;
|
||||
|
||||
++RC.mac[mod_id]->slice_info.n_dl;
|
||||
flexran_set_dl_slice_id(mod_id, newidx, slice_id);
|
||||
return newidx;
|
||||
int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
const int idx = flexran_find_dl_slice(mod_id, s->id);
|
||||
if (idx < 0) return 0;
|
||||
pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl;
|
||||
return dl->remove_slice(dl->slices, idx);
|
||||
}
|
||||
|
||||
int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
|
||||
int n = sli->n_dl;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (sli->dl[i].id == slice_id) return i;
|
||||
}
|
||||
|
||||
slice_info_t *si = RC.mac[mod_id]->pre_processor_dl.slices;
|
||||
for (int i = 0; i < si->num; ++i)
|
||||
if (si->s[i]->id == slice_id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
|
||||
|
||||
if (sli->n_dl <= 1) return -1;
|
||||
|
||||
if (sli->dl[slice_idx].sched_name) free(sli->dl[slice_idx].sched_name);
|
||||
|
||||
--sli->n_dl;
|
||||
|
||||
/* move last element to the position of the removed one */
|
||||
if (slice_idx != sli->n_dl)
|
||||
memcpy(&sli->dl[slice_idx], &sli->dl[sli->n_dl], sizeof(sli->dl[sli->n_dl]));
|
||||
|
||||
memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl]));
|
||||
/* all UEs that have been in the old slice are put into slice index 0 */
|
||||
//int *assoc_list = RC.mac[mod_id]->UE_info.assoc_dl_slice_idx;
|
||||
|
||||
//for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
|
||||
// if (assoc_list[i] == slice_idx)
|
||||
// assoc_list[i] = 0;
|
||||
//}
|
||||
|
||||
return 1;
|
||||
void flexran_get_dl_slice(mid_t mod_id,
|
||||
int slice_idx,
|
||||
Protocol__FlexSlice *slice,
|
||||
Protocol__FlexSliceAlgorithm algo) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
slice_t *s_ = RC.mac[mod_id]->pre_processor_dl.slices->s[slice_idx];
|
||||
slice->has_id = 1;
|
||||
slice->id = s_->id;
|
||||
slice->label = s_->label;
|
||||
slice->scheduler = s_->dl_algo.name;
|
||||
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET;
|
||||
switch (algo) {
|
||||
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
|
||||
slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic));
|
||||
if (!slice->static_) return;
|
||||
protocol__flex_slice_static__init(slice->static_);
|
||||
slice->static_->has_poslow = 1;
|
||||
slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow;
|
||||
slice->static_->has_poshigh = 1;
|
||||
slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh;
|
||||
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int flexran_get_num_dl_slices(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.n_dl;
|
||||
}
|
||||
|
||||
int flexran_get_intraslice_sharing_active(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.intraslice_share_active;
|
||||
}
|
||||
void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.intraslice_share_active = intraslice_active;
|
||||
}
|
||||
|
||||
int flexran_get_interslice_sharing_active(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.interslice_share_active;
|
||||
}
|
||||
void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.interslice_share_active = interslice_active;
|
||||
}
|
||||
|
||||
slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].id;
|
||||
}
|
||||
void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].id = slice_id;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].pct * 100.0f;
|
||||
}
|
||||
void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].pct = percentage / 100.0f;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].isol;
|
||||
}
|
||||
void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].isol = is_isolated;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].prio;
|
||||
}
|
||||
void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].prio = priority;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low;
|
||||
}
|
||||
void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low = poslow;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high;
|
||||
}
|
||||
void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high = poshigh;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs;
|
||||
}
|
||||
void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs = maxmcs;
|
||||
}
|
||||
|
||||
int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
if (!(*sorting_list)) {
|
||||
*sorting_list = calloc(CR_NUM, sizeof(Protocol__FlexDlSorting));
|
||||
|
||||
if (!(*sorting_list)) return -1;
|
||||
}
|
||||
|
||||
uint32_t policy = RC.mac[mod_id]->slice_info.dl[slice_idx].sorting;
|
||||
|
||||
for (int i = 0; i < CR_NUM; i++) {
|
||||
switch (policy >> 4 * (CR_NUM - 1 - i) & 0xF) {
|
||||
case CR_ROUND:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
|
||||
break;
|
||||
|
||||
case CR_SRB12:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_SRB12;
|
||||
break;
|
||||
|
||||
case CR_HOL:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_HOL;
|
||||
break;
|
||||
|
||||
case CR_LC:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LC;
|
||||
break;
|
||||
|
||||
case CR_CQI:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_CQI;
|
||||
break;
|
||||
|
||||
case CR_LCP:
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LCP;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* this should not happen, but a "default" */
|
||||
(*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CR_NUM;
|
||||
}
|
||||
void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
uint32_t policy = 0;
|
||||
|
||||
for (int i = 0; i < n && i < CR_NUM; i++) {
|
||||
switch (sorting_list[i]) {
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_ROUND:
|
||||
policy = policy << 4 | CR_ROUND;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_SRB12:
|
||||
policy = policy << 4 | CR_SRB12;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_HOL:
|
||||
policy = policy << 4 | CR_HOL;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_LC:
|
||||
policy = policy << 4 | CR_LC;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_CQI:
|
||||
policy = policy << 4 | CR_CQI;
|
||||
break;
|
||||
|
||||
case PROTOCOL__FLEX_DL_SORTING__CR_LCP:
|
||||
policy = policy << 4 | CR_LCP;
|
||||
break;
|
||||
|
||||
default: /* suppresses warnings */
|
||||
policy = policy << 4 | CR_ROUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill up with 0 == CR_ROUND */
|
||||
if (CR_NUM > n) policy = policy << 4 * (CR_NUM - n);
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].sorting = policy;
|
||||
}
|
||||
|
||||
Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
|
||||
|
||||
switch (RC.mac[mod_id]->slice_info.dl[slice_idx].accounting) {
|
||||
case POL_FAIR:
|
||||
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
|
||||
|
||||
case POL_GREEDY:
|
||||
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY;
|
||||
|
||||
default:
|
||||
return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR;
|
||||
}
|
||||
}
|
||||
void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
switch (accounting) {
|
||||
case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR:
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
|
||||
return;
|
||||
|
||||
case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY:
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_GREEDY;
|
||||
return;
|
||||
|
||||
default:
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return NULL;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name;
|
||||
}
|
||||
int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
|
||||
if (RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name)
|
||||
free(RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name);
|
||||
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name = strdup(name);
|
||||
RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb = dlsym(NULL, name);
|
||||
return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb != NULL;
|
||||
if (!RC.mac[mod_id]->pre_processor_dl.slices) return 0;
|
||||
return RC.mac[mod_id]->pre_processor_dl.slices->num;
|
||||
}
|
||||
|
||||
int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) {
|
||||
int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void *params = NULL;
|
||||
switch (s->params_case) {
|
||||
case PROTOCOL__FLEX_SLICE__PARAMS_STATIC:
|
||||
params = malloc(sizeof(static_slice_param_t));
|
||||
if (!params) return 0;
|
||||
((static_slice_param_t *)params)->posLow = s->static_->poslow;
|
||||
((static_slice_param_t *)params)->posHigh = s->static_->poshigh;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
|
||||
char *l = s->label ? strdup(s->label) : NULL;
|
||||
void *algo = &ul->ul_algo; // default scheduler
|
||||
if (s->scheduler) {
|
||||
algo = dlsym(NULL, s->scheduler);
|
||||
if (!algo) {
|
||||
free(params);
|
||||
LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler);
|
||||
return -15;
|
||||
}
|
||||
}
|
||||
return ul->addmod_slice(ul->slices, s->id, l, algo, params);
|
||||
}
|
||||
|
||||
int newidx = RC.mac[mod_id]->slice_info.n_ul;
|
||||
|
||||
if (newidx >= MAX_NUM_SLICES) return -1;
|
||||
|
||||
++RC.mac[mod_id]->slice_info.n_ul;
|
||||
flexran_set_ul_slice_id(mod_id, newidx, slice_id);
|
||||
return newidx;
|
||||
int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
const int idx = flexran_find_ul_slice(mod_id, s->id);
|
||||
if (idx < 0) return 0;
|
||||
pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul;
|
||||
return ul->remove_slice(ul->slices, idx);
|
||||
}
|
||||
|
||||
int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
|
||||
int n = sli->n_ul;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (sli->ul[i].id == slice_id) return i;
|
||||
}
|
||||
|
||||
slice_info_t *si = RC.mac[mod_id]->pre_processor_ul.slices;
|
||||
for (int i = 0; i < si->num; ++i)
|
||||
if (si->s[i]->id == slice_id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void flexran_get_ul_slice(mid_t mod_id,
|
||||
int slice_idx,
|
||||
Protocol__FlexSlice *slice,
|
||||
Protocol__FlexSliceAlgorithm algo) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
slice_t *s_ = RC.mac[mod_id]->pre_processor_ul.slices->s[slice_idx];
|
||||
slice->has_id = 1;
|
||||
slice->id = s_->id;
|
||||
slice->label = s_->label;
|
||||
slice->scheduler = s_->ul_algo.name;
|
||||
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET;
|
||||
switch (algo) {
|
||||
case PROTOCOL__FLEX_SLICE_ALGORITHM__Static:
|
||||
slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic));
|
||||
if (!slice->static_) return;
|
||||
protocol__flex_slice_static__init(slice->static_);
|
||||
slice->static_->has_poslow = 1;
|
||||
slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow;
|
||||
slice->static_->has_poshigh = 1;
|
||||
slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh;
|
||||
slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
slice_info_t *sli = &RC.mac[mod_id]->slice_info;
|
||||
|
||||
if (sli->n_ul <= 1) return -1;
|
||||
|
||||
if (sli->ul[slice_idx].sched_name) free(sli->ul[slice_idx].sched_name);
|
||||
|
||||
--sli->n_ul;
|
||||
|
||||
/* move last element to the position of the removed one */
|
||||
if (slice_idx != sli->n_ul)
|
||||
memcpy(&sli->ul[slice_idx], &sli->ul[sli->n_ul], sizeof(sli->ul[sli->n_ul]));
|
||||
|
||||
memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul]));
|
||||
/* all UEs that have been in the old slice are put into slice index 0 */
|
||||
//int *assoc_list = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx;
|
||||
|
||||
//for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) {
|
||||
// if (assoc_list[i] == slice_idx)
|
||||
// assoc_list[i] = 0;
|
||||
//}
|
||||
|
||||
return sli->n_ul;
|
||||
}
|
||||
|
||||
int flexran_get_num_ul_slices(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.n_ul;
|
||||
}
|
||||
|
||||
int flexran_ul_slice_exists(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul;
|
||||
}
|
||||
|
||||
slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].id;
|
||||
}
|
||||
void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].id = slice_id;
|
||||
}
|
||||
|
||||
int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].pct * 100.0f;
|
||||
}
|
||||
void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].pct = percentage / 100.0f;
|
||||
}
|
||||
|
||||
int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb;
|
||||
}
|
||||
|
||||
void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb = first_rb;
|
||||
}
|
||||
|
||||
int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs;
|
||||
}
|
||||
void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) {
|
||||
if (!mac_is_present(mod_id)) return;
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs = maxmcs;
|
||||
}
|
||||
|
||||
char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx) {
|
||||
if (!mac_is_present(mod_id)) return NULL;
|
||||
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name;
|
||||
}
|
||||
int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) {
|
||||
if (!mac_is_present(mod_id)) return 0;
|
||||
if (!RC.mac[mod_id]->pre_processor_ul.slices) return 0;
|
||||
return RC.mac[mod_id]->pre_processor_ul.slices->num;
|
||||
}
|
||||
|
||||
if (RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name)
|
||||
free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name);
|
||||
char *flexran_get_dl_scheduler_name(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return NULL;
|
||||
return RC.mac[mod_id]->pre_processor_dl.dl_algo.name;
|
||||
}
|
||||
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name = strdup(name);
|
||||
RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb = dlsym(NULL, name);
|
||||
return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL;
|
||||
int flexran_set_dl_scheduler(mid_t mod_id, char *sched) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void *d = dlsym(NULL, sched);
|
||||
if (!d) return -2;
|
||||
pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl;
|
||||
dl_pp->dl_algo.unset(&dl_pp->dl_algo.data);
|
||||
dl_pp->dl_algo = *(default_sched_dl_algo_t *) d;
|
||||
dl_pp->dl_algo.data = dl_pp->dl_algo.setup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *flexran_get_ul_scheduler_name(mid_t mod_id) {
|
||||
if (!mac_is_present(mod_id)) return NULL;
|
||||
return RC.mac[mod_id]->pre_processor_ul.ul_algo.name;
|
||||
}
|
||||
|
||||
int flexran_set_ul_scheduler(mid_t mod_id, char *sched) {
|
||||
if (!mac_is_present(mod_id)) return -1;
|
||||
void *d = dlsym(NULL, sched);
|
||||
if (!d) return -2;
|
||||
pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul;
|
||||
ul_pp->ul_algo.unset(&ul_pp->ul_algo.data);
|
||||
ul_pp->ul_algo = *(default_sched_ul_algo_t *) d;
|
||||
ul_pp->ul_algo.data = ul_pp->ul_algo.setup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************** S1AP **************************/
|
||||
@@ -3634,6 +3457,168 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return -1;
|
||||
if (!rrc_is_present(mod_id)) return -2;
|
||||
|
||||
/* Reconstruct S1AP_REGISTER_ENB_REQ */
|
||||
MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, S1AP_REGISTER_ENB_REQ);
|
||||
RCconfig_S1(m, mod_id);
|
||||
|
||||
const int CC_id = 0;
|
||||
eNB_RRC_INST *rrc = RC.rrc[CC_id];
|
||||
RrcConfigurationReq *conf = &rrc->configuration;
|
||||
S1AP_REGISTER_ENB_REQ(m).num_plmn = conf->num_plmn;
|
||||
for (int i = 0; i < conf->num_plmn; ++i) {
|
||||
S1AP_REGISTER_ENB_REQ(m).mcc[i] = conf->mcc[i];
|
||||
S1AP_REGISTER_ENB_REQ(m).mnc[i] = conf->mnc[i];
|
||||
S1AP_REGISTER_ENB_REQ(m).mnc_digit_length[i] = conf->mnc_digit_length[i];
|
||||
}
|
||||
|
||||
/* reconstruct MME list, it might have been updated since initial
|
||||
* configuration */
|
||||
S1AP_REGISTER_ENB_REQ(m).nb_mme = 0;
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
|
||||
const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
|
||||
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = mme->mme_s1_ip.ipv4;
|
||||
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme->mme_s1_ip.ipv4_address);
|
||||
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = mme->mme_s1_ip.ipv6;
|
||||
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6_address, mme->mme_s1_ip.ipv6_address);
|
||||
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = mme->broadcast_plmn_num;
|
||||
for (int i = 0; i < mme->broadcast_plmn_num; ++i)
|
||||
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = mme->broadcast_plmn_index[i];
|
||||
S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
|
||||
}
|
||||
|
||||
if (S1AP_REGISTER_ENB_REQ(m).nb_mme + n_mme > S1AP_MAX_NB_MME_IP_ADDRESS)
|
||||
return -1;
|
||||
|
||||
for (int i = 0; i < n_mme; ++i) {
|
||||
const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme;
|
||||
strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]);
|
||||
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1;
|
||||
S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0;
|
||||
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn;
|
||||
for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i)
|
||||
S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i;
|
||||
S1AP_REGISTER_ENB_REQ(m).nb_mme += 1;
|
||||
}
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) {
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap) return -1;
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
|
||||
if (mme->mme_s1_ip.ipv4
|
||||
&& strncmp(mme->mme_s1_ip.ipv4_address, mme_ipv4[0], 16) == 0)
|
||||
break;
|
||||
}
|
||||
if (!mme)
|
||||
return -2;
|
||||
|
||||
MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SCTP_CLOSE_ASSOCIATION);
|
||||
SCTP_CLOSE_ASSOCIATION(m).assoc_id = mme->assoc_id;
|
||||
itti_send_msg_to_task (TASK_SCTP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m);
|
||||
|
||||
switch (mme->state) {
|
||||
case S1AP_ENB_STATE_WAITING:
|
||||
s1ap->s1ap_mme_nb -= 1;
|
||||
if (s1ap->s1ap_mme_pending_nb > 0)
|
||||
s1ap->s1ap_mme_pending_nb -= 1;
|
||||
break;
|
||||
case S1AP_ENB_STATE_CONNECTED:
|
||||
case S1AP_ENB_OVERLOAD: /* I am not sure the decrements are right here */
|
||||
s1ap->s1ap_mme_nb -= 1;
|
||||
s1ap->s1ap_mme_associated_nb -= 1;
|
||||
break;
|
||||
case S1AP_ENB_STATE_DISCONNECTED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
RB_REMOVE(s1ap_mme_map, &s1ap->s1ap_mme_head, mme);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id) {
|
||||
if (!rrc_is_present(mod_id))
|
||||
return -1;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
if (!s1ap)
|
||||
return -2;
|
||||
|
||||
eNB_RRC_INST *rrc = RC.rrc[CC_id];
|
||||
RrcConfigurationReq *conf = &rrc->configuration;
|
||||
|
||||
uint8_t num_plmn_old = conf->num_plmn;
|
||||
uint16_t mcc[PLMN_LIST_MAX_SIZE];
|
||||
uint16_t mnc[PLMN_LIST_MAX_SIZE];
|
||||
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
|
||||
for (int i = 0; i < num_plmn_old; ++i) {
|
||||
mcc[i] = conf->mcc[i];
|
||||
mnc[i] = conf->mnc[i];
|
||||
mnc_digit_length[i] = conf->mnc_digit_length[i];
|
||||
}
|
||||
|
||||
conf->num_plmn = (uint8_t) n_plmn;
|
||||
for (int i = 0; i < conf->num_plmn; ++i) {
|
||||
conf->mcc[i] = plmn_id[i]->mcc;
|
||||
conf->mnc[i] = plmn_id[i]->mnc;
|
||||
conf->mnc_digit_length[i] = plmn_id[i]->mnc_length;
|
||||
}
|
||||
|
||||
rrc_eNB_carrier_data_t *carrier = &rrc->carrier[CC_id];
|
||||
extern uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier,
|
||||
int Mod_id,
|
||||
int CC_id,
|
||||
BOOLEAN_t brOption,
|
||||
RrcConfigurationReq *configuration);
|
||||
carrier->sizeof_SIB1 = do_SIB1(carrier, mod_id, CC_id, FALSE, conf);
|
||||
if (carrier->sizeof_SIB1 < 0)
|
||||
return -1337; /* SIB1 encoding failed, hell will probably break loose */
|
||||
|
||||
s1ap->num_plmn = (uint8_t) n_plmn;
|
||||
for (int i = 0; i < conf->num_plmn; ++i) {
|
||||
s1ap->mcc[i] = plmn_id[i]->mcc;
|
||||
s1ap->mnc[i] = plmn_id[i]->mnc;
|
||||
s1ap->mnc_digit_length[i] = plmn_id[i]->mnc_length;
|
||||
}
|
||||
|
||||
int bpn_failed = 0;
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) {
|
||||
for (int i = 0; i < mme->broadcast_plmn_num; ++i) {
|
||||
/* search the new index and update. If we don't find, we count this using
|
||||
* bpn_failed to now how many broadcast_plmns could not be updated */
|
||||
int idx = mme->broadcast_plmn_index[i];
|
||||
int omcc = mcc[idx];
|
||||
int omnc = mnc[idx];
|
||||
int omncl = mnc_digit_length[idx];
|
||||
int j = 0;
|
||||
for (j = 0; j < s1ap->num_plmn; ++j) {
|
||||
if (s1ap->mcc[j] == omcc
|
||||
&& s1ap->mnc[j] == omnc
|
||||
&& s1ap->mnc_digit_length[j] == omncl) {
|
||||
mme->broadcast_plmn_index[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == s1ap->num_plmn) /* could not find the old PLMN in the new ones */
|
||||
bpn_failed++;
|
||||
}
|
||||
}
|
||||
if (bpn_failed > 0)
|
||||
return -10000 - bpn_failed;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){
|
||||
if (!rrc_is_present(mod_id)) return -1;
|
||||
s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id);
|
||||
@@ -3644,7 +3629,7 @@ int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_con
|
||||
RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head){
|
||||
if (ue->eNB_ue_s1ap_id == enb_ue_s1ap_id) break;
|
||||
}
|
||||
if (ue == NULL) return -1;
|
||||
if (!ue) return 0; // UE does not exist: it might be connected but CN did not answer
|
||||
|
||||
if (ue->mme_ref->mme_s1_ip.ipv4)
|
||||
ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv4_address[0];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2240,7 +2240,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
|
||||
uint8_t first_ue_total[MAX_NUM_CCs][20];
|
||||
uint8_t first_ue_id[MAX_NUM_CCs][20];
|
||||
uint8_t ul_inactivity_num[MAX_NUM_CCs];
|
||||
uint8_t ul_inactivity_id[MAX_NUM_CCs][20]={0};
|
||||
uint8_t ul_inactivity_id[MAX_NUM_CCs][20]={{0}};
|
||||
// LTE_DL_FRAME_PARMS *frame_parms;
|
||||
uint8_t ulsch_ue_max_num[MAX_NUM_CCs];
|
||||
uint16_t saved_ulsch_dci[MAX_NUM_CCs];
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
+81
-105
@@ -155,9 +155,6 @@
|
||||
/*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */
|
||||
#define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE)
|
||||
|
||||
/*!\brief maximum number of slices / groups */
|
||||
#define MAX_NUM_SLICES 10
|
||||
|
||||
|
||||
#define U_PLANE_INACTIVITY_VALUE 0 /* defined 10ms order (zero means infinity) */
|
||||
|
||||
@@ -543,7 +540,6 @@ typedef enum {
|
||||
SCHED_MODE_FAIR_RR /// fair raund robin
|
||||
} SCHEDULER_MODES;
|
||||
|
||||
|
||||
/*! \brief temporary struct for ULSCH sched */
|
||||
typedef struct {
|
||||
rnti_t rnti;
|
||||
@@ -1150,9 +1146,6 @@ typedef struct {
|
||||
UE_list_t list;
|
||||
int num_UEs;
|
||||
boolean_t active[MAX_MOBILES_PER_ENB];
|
||||
|
||||
/// Sorting criteria for the UE list in the MAC preprocessor
|
||||
uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM];
|
||||
} UE_info_t;
|
||||
|
||||
/*! \brief deleting control information*/
|
||||
@@ -1171,101 +1164,6 @@ typedef struct {
|
||||
int tail_freelist; ///the tail position of the delete list
|
||||
} UE_free_list_t;
|
||||
|
||||
/**
|
||||
* slice specific scheduler for the DL
|
||||
*/
|
||||
typedef void (*slice_scheduler_dl)(module_id_t mod_id,
|
||||
int slice_idx,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe,
|
||||
int *mbsfn_flag);
|
||||
|
||||
typedef struct {
|
||||
slice_id_t id;
|
||||
|
||||
/// RB share for each slice
|
||||
float pct;
|
||||
|
||||
/// whether this slice is isolated from the others
|
||||
int isol;
|
||||
|
||||
int prio;
|
||||
|
||||
/// Frequency ranges for slice positioning
|
||||
int pos_low;
|
||||
int pos_high;
|
||||
|
||||
// max mcs for each slice
|
||||
int maxmcs;
|
||||
|
||||
/// criteria for sorting policies of the slices
|
||||
uint32_t sorting;
|
||||
|
||||
/// Accounting policy (just greedy(1) or fair(0) setting for now)
|
||||
int accounting;
|
||||
|
||||
/// name of available scheduler
|
||||
char *sched_name;
|
||||
|
||||
/// pointer to the slice specific scheduler in DL
|
||||
slice_scheduler_dl sched_cb;
|
||||
|
||||
} slice_sched_conf_dl_t;
|
||||
|
||||
typedef void (*slice_scheduler_ul)(module_id_t mod_id,
|
||||
int slice_idx,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe,
|
||||
unsigned char sched_subframe,
|
||||
uint16_t *first_rb);
|
||||
|
||||
typedef struct {
|
||||
slice_id_t id;
|
||||
|
||||
/// RB share for each slice
|
||||
float pct;
|
||||
|
||||
// MAX MCS for each slice
|
||||
int maxmcs;
|
||||
|
||||
/// criteria for sorting policies of the slices
|
||||
uint32_t sorting;
|
||||
|
||||
/// starting RB (RB offset) of UL scheduling
|
||||
int first_rb;
|
||||
|
||||
/// name of available scheduler
|
||||
char *sched_name;
|
||||
|
||||
/// pointer to the slice specific scheduler in UL
|
||||
slice_scheduler_ul sched_cb;
|
||||
|
||||
} slice_sched_conf_ul_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// counter used to indicate when all slices have pre-allocated UEs
|
||||
//int slice_counter;
|
||||
|
||||
/// indicates whether remaining RBs after first intra-slice allocation will
|
||||
/// be allocated to UEs of the same slice
|
||||
int intraslice_share_active;
|
||||
/// indicates whether remaining RBs after slice allocation will be
|
||||
/// allocated to UEs of another slice. Isolated slices will be ignored
|
||||
int interslice_share_active;
|
||||
|
||||
/// number of active DL slices
|
||||
int n_dl;
|
||||
slice_sched_conf_dl_t dl[MAX_NUM_SLICES];
|
||||
|
||||
/// number of active UL slices
|
||||
int n_ul;
|
||||
slice_sched_conf_ul_t ul[MAX_NUM_SLICES];
|
||||
|
||||
/// common rb allocation list between slices
|
||||
uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX];
|
||||
} slice_info_t;
|
||||
|
||||
/**
|
||||
* describes contiguous RBs
|
||||
*/
|
||||
@@ -1274,6 +1172,82 @@ typedef struct {
|
||||
int length;
|
||||
} contig_rbs_t;
|
||||
|
||||
/**
|
||||
* definition of a scheduling algorithm implementation used in the
|
||||
* default DL scheduler
|
||||
*/
|
||||
typedef struct {
|
||||
char *name;
|
||||
void *(*setup)(void);
|
||||
void (*unset)(void **);
|
||||
int (*run)(
|
||||
module_id_t, int, int, int, UE_list_t *, int, int, uint8_t *, void *);
|
||||
void *data;
|
||||
} default_sched_dl_algo_t;
|
||||
|
||||
/**
|
||||
* definition of a scheduling algorithm implementation used in the
|
||||
* default UL scheduler
|
||||
*/
|
||||
typedef struct {
|
||||
char *name;
|
||||
void *(*setup)(void);
|
||||
void (*unset)(void **);
|
||||
int (*run)(
|
||||
module_id_t, int, int, int, int, int, UE_list_t *, int, int, contig_rbs_t *, void *);
|
||||
void *data;
|
||||
} default_sched_ul_algo_t;
|
||||
|
||||
typedef void (*pp_impl_dl)(module_id_t mod_id,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe);
|
||||
typedef void (*pp_impl_ul)(module_id_t mod_id,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
sub_frame_t subframe,
|
||||
frame_t sched_frame,
|
||||
sub_frame_t sched_subframe);
|
||||
|
||||
struct slice_info_s;
|
||||
typedef struct {
|
||||
int algorithm;
|
||||
|
||||
/// inform the slice algorithm about a new UE
|
||||
void (*add_UE)(struct slice_info_s *s, int UE_id);
|
||||
/// inform the slice algorithm about a UE that disconnected
|
||||
void (*remove_UE)(struct slice_info_s *s, int UE_id);
|
||||
/// move a UE to a slice in DL/UL, -1 means don't move (no-op).
|
||||
void (*move_UE)(struct slice_info_s *s, int UE_id, int idx);
|
||||
|
||||
/// Adds a new slice through admission control. slice_params are
|
||||
/// algorithm-specific parameters. sched is either a default_sched_ul_algo_t
|
||||
/// or default_sched_dl_algo_t, depending on whether this implementation
|
||||
/// handles UL/DL. If slice at index exists, updates existing
|
||||
/// slice. Returns index of new slice or -1 on failure.
|
||||
int (*addmod_slice)(struct slice_info_s *s,
|
||||
int id,
|
||||
char *label,
|
||||
void *sched,
|
||||
void *slice_params);
|
||||
/// Returns slice through slice_idx. 1 if successful, 0 if not.
|
||||
int (*remove_slice)(struct slice_info_s *s, uint8_t slice_idx);
|
||||
|
||||
union {
|
||||
pp_impl_dl dl;
|
||||
pp_impl_ul ul;
|
||||
};
|
||||
|
||||
union {
|
||||
default_sched_ul_algo_t ul_algo;
|
||||
default_sched_dl_algo_t dl_algo;
|
||||
};
|
||||
|
||||
void (*destroy)(struct slice_info_s **s);
|
||||
|
||||
struct slice_info_s *slices;
|
||||
} pp_impl_param_t;
|
||||
|
||||
/*! \brief eNB common channels */
|
||||
typedef struct {
|
||||
int physCellId;
|
||||
@@ -1395,9 +1369,6 @@ typedef struct eNB_MAC_INST_s {
|
||||
uint32_t ul_handle;
|
||||
UE_info_t UE_info;
|
||||
|
||||
/// slice-related configuration
|
||||
slice_info_t slice_info;
|
||||
|
||||
///subband bitmap configuration
|
||||
SBMAP_CONF sbmap_conf;
|
||||
/// CCE table used to build DCI scheduling information
|
||||
@@ -1432,6 +1403,11 @@ typedef struct eNB_MAC_INST_s {
|
||||
UE_free_list_t UE_free_list;
|
||||
/// for scheduling selection
|
||||
SCHEDULER_MODES scheduler_mode;
|
||||
/// Default scheduler: Pre-processor implementation. Algorithms for UL/DL
|
||||
/// are called by ULSCH/DLSCH, respectively. Pro-processor implementation can
|
||||
/// encapsulate slicing.
|
||||
pp_impl_param_t pre_processor_dl;
|
||||
pp_impl_param_t pre_processor_ul;
|
||||
|
||||
int32_t puSch10xSnr;
|
||||
int32_t puCch10xSnr;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+17
-31
@@ -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;
|
||||
|
||||
+475
-154
@@ -69,31 +69,367 @@ int get_rbg_size_last(module_id_t Mod_id, int CC_id) {
|
||||
return RBGsize;
|
||||
}
|
||||
|
||||
int g_start_ue_dl = -1;
|
||||
int round_robin_dl(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int n_rbg_sched,
|
||||
uint8_t *rbgalloc_mask) {
|
||||
void *rr_dl_setup(void) {
|
||||
void *data = malloc(sizeof(int));
|
||||
*(int *) data = 0;
|
||||
AssertFatal(data, "could not allocate data in %s()\n", __func__);
|
||||
return data;
|
||||
}
|
||||
void rr_dl_unset(void **data) {
|
||||
if (*data)
|
||||
free(*data);
|
||||
*data = NULL;
|
||||
}
|
||||
int rr_dl_run(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int n_rbg_sched,
|
||||
uint8_t *rbgalloc_mask,
|
||||
void *data) {
|
||||
DevAssert(UE_list->head >= 0);
|
||||
DevAssert(n_rbg_sched > 0);
|
||||
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
|
||||
const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id);
|
||||
int num_ue_req = 0;
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
|
||||
int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request
|
||||
memset(rb_required, 0, sizeof(rb_required));
|
||||
|
||||
int rbg = 0;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++)
|
||||
; /* fast-forward to first allowed RBG */
|
||||
|
||||
// Calculate the amount of RBs every UE wants to send.
|
||||
/* just start with the UE after the one we had last time. If it does not
|
||||
* exist, this will start at the head */
|
||||
int *start_ue = data;
|
||||
*start_ue = next_ue_list_looped(UE_list, *start_ue);
|
||||
|
||||
int UE_id = *start_ue;
|
||||
UE_list_t UE_sched;
|
||||
int *cur_UE = &UE_sched.head;
|
||||
// Allocate retransmissions, and mark UEs with new transmissions
|
||||
do {
|
||||
// check whether there are HARQ retransmissions
|
||||
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
|
||||
if (round != 8) { // retransmission: allocate
|
||||
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
||||
if (nb_rb == 0)
|
||||
goto skip_ue;
|
||||
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
|
||||
// needs more RBGs than we can allocate
|
||||
if (nb_rbg > n_rbg_sched) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
|
||||
UE_id, nb_rbg, n_rbg_sched);
|
||||
goto skip_ue;
|
||||
}
|
||||
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
|
||||
// if we allocate the last RBG this one should have the full RBGsize
|
||||
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
|
||||
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
|
||||
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
|
||||
goto skip_ue;
|
||||
}
|
||||
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0)
|
||||
goto skip_ue; // cannot allocate CCE
|
||||
ue_ctrl->pre_dci_dl_pdu_idx = idx;
|
||||
// retransmissions: directly allocate
|
||||
n_rbg_sched -= nb_rbg;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
|
||||
for (; nb_rbg > 0; rbg++) {
|
||||
if (!rbgalloc_mask[rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
|
||||
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
|
||||
frame, subframe, n_rbg_sched, UE_id, round,
|
||||
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id]);
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
/* if there are no UEs that can be allocated anymore, return */
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
} else {
|
||||
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) {
|
||||
*cur_UE = UE_id;
|
||||
cur_UE = &UE_sched.next[UE_id];
|
||||
}
|
||||
}
|
||||
|
||||
skip_ue:
|
||||
UE_id = next_ue_list_looped(UE_list, UE_id);
|
||||
} while (UE_id != *start_ue);
|
||||
*cur_UE = -1; // mark end
|
||||
|
||||
if (UE_sched.head < 0)
|
||||
return n_rbg_sched; // no UE has a transmission
|
||||
|
||||
// after allocating retransmissions: pre-allocate CCE, compute number of
|
||||
// requested RBGs
|
||||
max_num_ue = min(max_num_ue, n_rbg_sched);
|
||||
int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request
|
||||
cur_UE = &UE_sched.head;
|
||||
while (*cur_UE >= 0 && max_num_ue > 0) {
|
||||
const int UE_id = *cur_UE;
|
||||
cur_UE = &UE_sched.next[UE_id]; // go to next
|
||||
const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0) {
|
||||
LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id);
|
||||
continue;
|
||||
}
|
||||
UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx;
|
||||
const int mcs = cqi_to_mcs[cqi];
|
||||
UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs;
|
||||
const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total;
|
||||
rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize);
|
||||
max_num_ue--;
|
||||
}
|
||||
*cur_UE = -1; // not all UEs might be allocated, mark end
|
||||
|
||||
/* for one UE after the next: allocate resources */
|
||||
cur_UE = &UE_sched.head;
|
||||
while (*cur_UE >= 0) {
|
||||
const int UE_id = *cur_UE;
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG;
|
||||
rb_required[UE_id] -= sRBG;
|
||||
if (rb_required[UE_id] <= 0) {
|
||||
*cur_UE = UE_sched.next[*cur_UE];
|
||||
if (*cur_UE < 0)
|
||||
cur_UE = &UE_sched.head;
|
||||
} else {
|
||||
cur_UE = UE_sched.next[*cur_UE] < 0 ? &UE_sched.head : &UE_sched.next[*cur_UE];
|
||||
}
|
||||
n_rbg_sched--;
|
||||
if (n_rbg_sched <= 0)
|
||||
break;
|
||||
for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
|
||||
return n_rbg_sched;
|
||||
}
|
||||
default_sched_dl_algo_t round_robin_dl = {
|
||||
.name = "round_robin_dl",
|
||||
.setup = rr_dl_setup,
|
||||
.unset = rr_dl_unset,
|
||||
.run = rr_dl_run,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
|
||||
void *pf_dl_setup(void) {
|
||||
void *data = calloc(MAX_MOBILES_PER_ENB, sizeof(float));
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; i++)
|
||||
*(float *) data = 0.0f;
|
||||
AssertFatal(data, "could not allocate data in %s()\n", __func__);
|
||||
return data;
|
||||
}
|
||||
void pf_dl_unset(void **data) {
|
||||
if (*data)
|
||||
free(*data);
|
||||
*data = NULL;
|
||||
}
|
||||
int pf_wbcqi_dl_run(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int n_rbg_sched,
|
||||
uint8_t *rbgalloc_mask,
|
||||
void *data) {
|
||||
DevAssert(UE_list->head >= 0);
|
||||
DevAssert(n_rbg_sched > 0);
|
||||
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
|
||||
const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id);
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
|
||||
int rbg = 0;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++)
|
||||
; /* fast-forward to first allowed RBG */
|
||||
|
||||
UE_list_t UE_sched; // UEs that could be scheduled
|
||||
int *uep = &UE_sched.head;
|
||||
float *thr_ue = data;
|
||||
float coeff_ue[MAX_MOBILES_PER_ENB];
|
||||
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
const float a = 0.0005f; // corresponds to 200ms window
|
||||
const uint32_t b = UE_info->eNB_UE_stats[CC_id][UE_id].TBS;
|
||||
thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b;
|
||||
|
||||
// check whether there are HARQ retransmissions
|
||||
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||
const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const uint8_t round = ue_ctrl->round[CC_id][harq_pid];
|
||||
if (round != 8) { // retransmission: allocate
|
||||
const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid];
|
||||
if (nb_rb == 0)
|
||||
continue;
|
||||
int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize;
|
||||
// needs more RBGs than we can allocate
|
||||
if (nb_rbg > n_rbg_sched) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs more RBGs (%d) than we have (%d)\n",
|
||||
UE_id, nb_rbg, n_rbg_sched);
|
||||
continue;
|
||||
}
|
||||
// ensure that the number of RBs can be contained by the RBGs (!), i.e.
|
||||
// if we allocate the last RBG this one should have the full RBGsize
|
||||
if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched
|
||||
&& rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) {
|
||||
LOG_D(MAC,
|
||||
"retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n",
|
||||
UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize);
|
||||
continue;
|
||||
}
|
||||
const uint8_t cqi = ue_ctrl->dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0)
|
||||
continue; // cannot allocate CCE
|
||||
ue_ctrl->pre_dci_dl_pdu_idx = idx;
|
||||
// retransmissions: directly allocate
|
||||
n_rbg_sched -= nb_rbg;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb;
|
||||
for (; nb_rbg > 0; rbg++) {
|
||||
if (!rbgalloc_mask[rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
"%4d.%d n_rbg_sched %d after retransmission reservation for UE %d "
|
||||
"round %d retx nb_rb %d pre_nb_available_rbs %d\n",
|
||||
frame, subframe, n_rbg_sched, UE_id, round,
|
||||
UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid],
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id]);
|
||||
/* if there are no more RBG to give, return */
|
||||
if (n_rbg_sched <= 0)
|
||||
return 0;
|
||||
max_num_ue--;
|
||||
/* if there are no UEs that can be allocated anymore, return */
|
||||
if (max_num_ue == 0)
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
} else {
|
||||
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0)
|
||||
continue;
|
||||
|
||||
const int mcs = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]];
|
||||
const uint32_t tbs = get_TBS_DL(mcs, RBGsize);
|
||||
coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id];
|
||||
//LOG_I(MAC, " pf UE %d: old TBS %d thr %f MCS %d TBS %d coeff %f\n",
|
||||
// UE_id, b, thr_ue[UE_id], mcs, tbs, coeff_ue[UE_id]);
|
||||
*uep = UE_id;
|
||||
uep = &UE_sched.next[UE_id];
|
||||
}
|
||||
}
|
||||
*uep = -1;
|
||||
|
||||
while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) {
|
||||
int *max = &UE_sched.head; /* assume head is max */
|
||||
int *p = &UE_sched.next[*max];
|
||||
while (*p >= 0) {
|
||||
/* if the current one has larger coeff, save for later */
|
||||
if (coeff_ue[*p] > coeff_ue[*max])
|
||||
max = p;
|
||||
p = &UE_sched.next[*p];
|
||||
}
|
||||
/* remove the max one */
|
||||
const int UE_id = *max;
|
||||
p = &UE_sched.next[*max];
|
||||
*max = UE_sched.next[*max];
|
||||
*p = -1;
|
||||
|
||||
const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0)
|
||||
continue;
|
||||
UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx;
|
||||
|
||||
max_num_ue--;
|
||||
|
||||
/* allocate as much as possible */
|
||||
const int mcs = cqi_to_mcs[cqi];
|
||||
UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs;
|
||||
int req = find_nb_rb_DL(mcs,
|
||||
UE_info->UE_template[CC_id][UE_id].dl_buffer_total,
|
||||
n_rbg_sched * RBGsize,
|
||||
RBGsize);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
while (req > 0 && n_rbg_sched > 0) {
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG;
|
||||
req -= sRBG;
|
||||
n_rbg_sched--;
|
||||
for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
}
|
||||
|
||||
return n_rbg_sched;
|
||||
}
|
||||
default_sched_dl_algo_t proportional_fair_wbcqi_dl = {
|
||||
.name = "proportional_fair_wbcqi_dl",
|
||||
.setup = pf_dl_setup,
|
||||
.unset = pf_dl_unset,
|
||||
.run = pf_wbcqi_dl_run,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
void *mt_dl_setup(void) {
|
||||
return NULL;
|
||||
}
|
||||
void mt_dl_unset(void **data) {
|
||||
*data = NULL;
|
||||
}
|
||||
int mt_wbcqi_dl_run(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int n_rbg_sched,
|
||||
uint8_t *rbgalloc_mask,
|
||||
void *data) {
|
||||
DevAssert(UE_list->head >= 0);
|
||||
DevAssert(n_rbg_sched > 0);
|
||||
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
|
||||
const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id);
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
|
||||
int rbg = 0;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++)
|
||||
; /* fast-forward to first allowed RBG */
|
||||
|
||||
UE_list_t UE_sched; // UEs that could be scheduled
|
||||
int *uep = &UE_sched.head;
|
||||
|
||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
// check whether there are HARQ retransmissions
|
||||
const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||
@@ -133,6 +469,7 @@ int round_robin_dl(module_id_t Mod_id,
|
||||
if (!rbgalloc_mask[rbg])
|
||||
continue;
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
nb_rbg--;
|
||||
}
|
||||
LOG_D(MAC,
|
||||
@@ -150,90 +487,69 @@ int round_robin_dl(module_id_t Mod_id,
|
||||
return n_rbg_sched;
|
||||
for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
} else {
|
||||
const int dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]];
|
||||
UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = dlsch_mcs1;
|
||||
rb_required[UE_id] =
|
||||
find_nb_rb_DL(dlsch_mcs1,
|
||||
UE_info->UE_template[CC_id][UE_id].dl_buffer_total,
|
||||
n_rbg_sched * RBGsize,
|
||||
RBGsize);
|
||||
if (rb_required[UE_id] > 0)
|
||||
num_ue_req++;
|
||||
LOG_D(MAC,
|
||||
"%d/%d UE_id %d rb_required %d n_rbg_sched %d\n",
|
||||
frame,
|
||||
subframe,
|
||||
UE_id,
|
||||
rb_required[UE_id],
|
||||
n_rbg_sched);
|
||||
if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0)
|
||||
continue;
|
||||
*uep = UE_id;
|
||||
uep = &UE_sched.next[UE_id];
|
||||
}
|
||||
}
|
||||
*uep = -1;
|
||||
|
||||
if (num_ue_req == 0)
|
||||
return n_rbg_sched; // no UE has a transmission
|
||||
while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) {
|
||||
int *max = &UE_sched.head; /* assume head is max */
|
||||
int *p = &UE_sched.next[*max];
|
||||
while (*p >= 0) {
|
||||
/* if the current one has better CQI, or the same and more data */
|
||||
const uint8_t maxCqi = UE_info->UE_sched_ctrl[*max].dl_cqi[CC_id];
|
||||
const uint32_t maxB = UE_info->UE_template[CC_id][*max].dl_buffer_total;
|
||||
const uint8_t pCqi = UE_info->UE_sched_ctrl[*p].dl_cqi[CC_id];
|
||||
const uint32_t pB = UE_info->UE_template[CC_id][*p].dl_buffer_total;
|
||||
if (pCqi > maxCqi || (pCqi == maxCqi && pB > maxB))
|
||||
max = p;
|
||||
p = &UE_sched.next[*p];
|
||||
}
|
||||
/* remove the max one */
|
||||
const int UE_id = *max;
|
||||
p = &UE_sched.next[*max];
|
||||
*max = UE_sched.next[*max];
|
||||
*p = -1;
|
||||
|
||||
// after allocating retransmissions: build list of UE to allocate.
|
||||
// if start_UE does not exist anymore (detach etc), start at first UE
|
||||
if (g_start_ue_dl == -1)
|
||||
g_start_ue_dl = UE_list->head;
|
||||
int UE_id = g_start_ue_dl;
|
||||
UE_list_t UE_sched;
|
||||
int rb_required_total = 0;
|
||||
int num_ue_sched = 0;
|
||||
max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched);
|
||||
int *cur_UE = &UE_sched.head;
|
||||
while (num_ue_sched < max_num_ue) {
|
||||
while (rb_required[UE_id] == 0)
|
||||
UE_id = next_ue_list_looped(UE_list, UE_id);
|
||||
const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
|
||||
const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi);
|
||||
if (idx < 0) {
|
||||
LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id);
|
||||
num_ue_req--;
|
||||
max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched);
|
||||
UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate
|
||||
if (idx < 0)
|
||||
continue;
|
||||
}
|
||||
UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx;
|
||||
*cur_UE = UE_id;
|
||||
cur_UE = &UE_sched.next[UE_id];
|
||||
rb_required_total += rb_required[UE_id];
|
||||
num_ue_sched++;
|
||||
UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate
|
||||
}
|
||||
*cur_UE = -1;
|
||||
|
||||
/* for one UE after the next: allocate resources */
|
||||
for (int UE_id = UE_sched.head; UE_id >= 0;
|
||||
UE_id = next_ue_list_looped(&UE_sched, UE_id)) {
|
||||
if (rb_required[UE_id] <= 0)
|
||||
continue;
|
||||
max_num_ue--;
|
||||
|
||||
/* allocate as much as possible */
|
||||
const int mcs = cqi_to_mcs[cqi];
|
||||
UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs;
|
||||
int req = find_nb_rb_DL(mcs,
|
||||
UE_info->UE_template[CC_id][UE_id].dl_buffer_total,
|
||||
n_rbg_sched * RBGsize,
|
||||
RBGsize);
|
||||
UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG;
|
||||
rb_required[UE_id] -= sRBG;
|
||||
rb_required_total -= sRBG;
|
||||
if (rb_required_total <= 0)
|
||||
break;
|
||||
n_rbg_sched--;
|
||||
if (n_rbg_sched <= 0)
|
||||
break;
|
||||
for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
|
||||
/* if not all UEs could be allocated in this round */
|
||||
if (num_ue_req > max_num_ue) {
|
||||
/* go to the first one we missed */
|
||||
for (int i = 0; i < max_num_ue; ++i)
|
||||
g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl);
|
||||
} else {
|
||||
/* else, just start with the next UE next time */
|
||||
g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl);
|
||||
while (req > 0 && n_rbg_sched > 0) {
|
||||
ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1;
|
||||
rbgalloc_mask[rbg] = 0;
|
||||
const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize;
|
||||
ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG;
|
||||
req -= sRBG;
|
||||
n_rbg_sched--;
|
||||
for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ;
|
||||
}
|
||||
}
|
||||
|
||||
return n_rbg_sched;
|
||||
}
|
||||
default_sched_dl_algo_t maximum_throughput_wbcqi_dl = {
|
||||
.name = "maximum_throughput_wbcqi_dl",
|
||||
.setup = mt_dl_setup,
|
||||
.unset = mt_dl_unset,
|
||||
.run = mt_wbcqi_dl_run,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
// This function stores the downlink buffer for all the logical channels
|
||||
void
|
||||
@@ -323,19 +639,18 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframeP) {
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
eNB_MAC_INST *mac = RC.mac[Mod_id];
|
||||
UE_info_t *UE_info = &mac->UE_info;
|
||||
const int N_RBG = to_rbg(mac->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
const int RBGsize = get_min_rb_unit(Mod_id, CC_id);
|
||||
|
||||
store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP);
|
||||
|
||||
UE_list_t UE_to_sched;
|
||||
UE_to_sched.head = -1;
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
|
||||
UE_to_sched.next[i] = -1;
|
||||
int *cur = &UE_to_sched.head;
|
||||
|
||||
int first = 1;
|
||||
int last_UE_id = -1;
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
const UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id];
|
||||
@@ -368,20 +683,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
}
|
||||
|
||||
/* define UEs to schedule */
|
||||
if (first) {
|
||||
first = 0;
|
||||
UE_to_sched.head = UE_id;
|
||||
} else {
|
||||
UE_to_sched.next[last_UE_id] = UE_id;
|
||||
}
|
||||
UE_to_sched.next[UE_id] = -1;
|
||||
last_UE_id = UE_id;
|
||||
*cur = UE_id;
|
||||
cur = &UE_to_sched.next[UE_id];
|
||||
}
|
||||
*cur = -1;
|
||||
|
||||
if (UE_to_sched.head < 0)
|
||||
return;
|
||||
|
||||
uint8_t *vrb_map = RC.mac[Mod_id]->common_channels[CC_id].vrb_map;
|
||||
uint8_t *vrb_map = mac->common_channels[CC_id].vrb_map;
|
||||
uint8_t rbgalloc_mask[N_RBG_MAX];
|
||||
int n_rbg_sched = 0;
|
||||
for (int i = 0; i < N_RBG; i++) {
|
||||
@@ -393,14 +703,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
n_rbg_sched += rbgalloc_mask[i];
|
||||
}
|
||||
|
||||
round_robin_dl(Mod_id,
|
||||
CC_id,
|
||||
frameP,
|
||||
subframeP,
|
||||
&UE_to_sched,
|
||||
4, // max_num_ue
|
||||
n_rbg_sched,
|
||||
rbgalloc_mask);
|
||||
mac->pre_processor_dl.dl_algo.run(Mod_id,
|
||||
CC_id,
|
||||
frameP,
|
||||
subframeP,
|
||||
&UE_to_sched,
|
||||
4, // max_num_ue
|
||||
n_rbg_sched,
|
||||
rbgalloc_mask,
|
||||
mac->pre_processor_dl.dl_algo.data);
|
||||
|
||||
// the following block is meant for validation of the pre-processor to check
|
||||
// whether all UE allocations are non-overlapping and is not necessary for
|
||||
@@ -512,17 +823,28 @@ int pp_find_rb_table_index(int approximate) {
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
int g_start_ue_ul = -1;
|
||||
int round_robin_ul(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
int sched_frame,
|
||||
int sched_subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int num_contig_rb,
|
||||
contig_rbs_t *rbs) {
|
||||
void *rr_ul_setup(void) {
|
||||
void *data = malloc(sizeof(int));
|
||||
*(int *) data = 0;
|
||||
AssertFatal(data, "could not allocate data in %s()\n", __func__);
|
||||
return data;
|
||||
}
|
||||
void rr_ul_unset(void **data) {
|
||||
if (*data)
|
||||
free(*data);
|
||||
*data = NULL;
|
||||
}
|
||||
int rr_ul_run(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frame,
|
||||
int subframe,
|
||||
int sched_frame,
|
||||
int sched_subframe,
|
||||
UE_list_t *UE_list,
|
||||
int max_num_ue,
|
||||
int num_contig_rb,
|
||||
contig_rbs_t *rbs,
|
||||
void *data) {
|
||||
AssertFatal(num_contig_rb <= 2, "cannot handle more than two contiguous RB regions\n");
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
const int max_rb = num_contig_rb > 1 ? MAX(rbs[0].length, rbs[1].length) : rbs[0].length;
|
||||
@@ -662,9 +984,10 @@ int round_robin_ul(module_id_t Mod_id,
|
||||
end = la > lb ? 2 : -1;
|
||||
}
|
||||
|
||||
if (g_start_ue_ul == -1)
|
||||
g_start_ue_ul = UE_list->head;
|
||||
int sUE_id = g_start_ue_ul;
|
||||
int *start_ue = data;
|
||||
if (*start_ue == -1)
|
||||
*start_ue = UE_list->head;
|
||||
int sUE_id = *start_ue;
|
||||
int rb_idx_given[MAX_MOBILES_PER_ENB];
|
||||
memset(rb_idx_given, 0, sizeof(rb_idx_given));
|
||||
|
||||
@@ -742,35 +1065,35 @@ int round_robin_ul(module_id_t Mod_id,
|
||||
}
|
||||
}
|
||||
|
||||
/* if not all UEs could be allocated in this round */
|
||||
if (num_ue_req > max_num_ue) {
|
||||
/* go to the first one we missed */
|
||||
for (int i = 0; i < max_num_ue; ++i)
|
||||
g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul);
|
||||
} else {
|
||||
/* else, just start with the next UE next time */
|
||||
g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul);
|
||||
}
|
||||
/* just start with the next UE next time */
|
||||
*start_ue = next_ue_list_looped(UE_list, *start_ue);
|
||||
|
||||
return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0);
|
||||
}
|
||||
default_sched_ul_algo_t round_robin_ul = {
|
||||
.name = "round_robin_ul",
|
||||
.setup = rr_ul_setup,
|
||||
.unset = rr_ul_unset,
|
||||
.run = rr_ul_run,
|
||||
.data = NULL
|
||||
};
|
||||
|
||||
void ulsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
int CC_id,
|
||||
int frameP,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframeP,
|
||||
int sched_frameP,
|
||||
unsigned char sched_subframeP) {
|
||||
UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info;
|
||||
const int N_RB_UL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].ul_Bandwidth);
|
||||
COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id];
|
||||
frame_t sched_frameP,
|
||||
sub_frame_t sched_subframeP) {
|
||||
eNB_MAC_INST *mac = RC.mac[Mod_id];
|
||||
UE_info_t *UE_info = &mac->UE_info;
|
||||
const int N_RB_UL = to_prb(mac->common_channels[CC_id].ul_Bandwidth);
|
||||
COMMON_channels_t *cc = &mac->common_channels[CC_id];
|
||||
|
||||
UE_list_t UE_to_sched;
|
||||
UE_to_sched.head = -1;
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
|
||||
UE_to_sched.next[i] = -1;
|
||||
int *cur = &UE_to_sched.head;
|
||||
|
||||
int last_UE_id = -1;
|
||||
for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
|
||||
UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id];
|
||||
UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||
@@ -793,13 +1116,10 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
continue;
|
||||
|
||||
/* define UEs to schedule */
|
||||
if (UE_to_sched.head < 0)
|
||||
UE_to_sched.head = UE_id;
|
||||
else
|
||||
UE_to_sched.next[last_UE_id] = UE_id;
|
||||
UE_to_sched.next[UE_id] = -1;
|
||||
last_UE_id = UE_id;
|
||||
*cur = UE_id;
|
||||
cur = &UE_to_sched.next[UE_id];
|
||||
}
|
||||
*cur = -1;
|
||||
|
||||
if (UE_to_sched.head < 0)
|
||||
return;
|
||||
@@ -820,16 +1140,17 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
}
|
||||
}
|
||||
|
||||
round_robin_ul(Mod_id,
|
||||
CC_id,
|
||||
frameP,
|
||||
subframeP,
|
||||
sched_frameP,
|
||||
sched_subframeP,
|
||||
&UE_to_sched,
|
||||
4, // max_num_ue
|
||||
n_contig,
|
||||
rbs);
|
||||
mac->pre_processor_ul.ul_algo.run(Mod_id,
|
||||
CC_id,
|
||||
frameP,
|
||||
subframeP,
|
||||
sched_frameP,
|
||||
sched_subframeP,
|
||||
&UE_to_sched,
|
||||
4, // max_num_ue
|
||||
n_contig,
|
||||
rbs,
|
||||
mac->pre_processor_ul.ul_algo.data);
|
||||
|
||||
// the following block is meant for validation of the pre-processor to check
|
||||
// whether all UE allocations are non-overlapping and is not necessary for
|
||||
@@ -848,7 +1169,7 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
continue;
|
||||
|
||||
print = 1;
|
||||
uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id],
|
||||
uint8_t harq_pid = subframe2harqpid(&mac->common_channels[CC_id],
|
||||
sched_frameP, sched_subframeP);
|
||||
LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n",
|
||||
frameP,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "NR_MAC_UE/mac_proto.h"
|
||||
#include "NR_MAC-CellGroupConfig.h"
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "SCHED_NR/phy_frame_config_nr.h"
|
||||
|
||||
int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg,
|
||||
int mu,
|
||||
@@ -326,6 +325,84 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
}
|
||||
|
||||
/** \brief This function is relavant for the UE procedures for control. It loads the search spaces, the BWPs and the CORESETs into the MAC instance and
|
||||
\brief performs assert checks on the relevant RRC configuration.
|
||||
@param NR_UE_MAC_INST_t mac: pointer to local MAC instance
|
||||
@returns void
|
||||
*/
|
||||
void config_control_ue(NR_UE_MAC_INST_t *mac){
|
||||
|
||||
uint8_t bwp_id = 1, coreset_id = 1, ss_id;
|
||||
NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated;
|
||||
AssertFatal(scd->downlinkBWP_ToAddModList != NULL, "downlinkBWP_ToAddModList is null\n");
|
||||
AssertFatal(scd->downlinkBWP_ToAddModList->list.count == 1, "downlinkBWP_ToAddModList->list->count is %d\n", scd->downlinkBWP_ToAddModList->list.count);
|
||||
|
||||
NR_BWP_DownlinkCommon_t *bwp_Common = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Common;
|
||||
AssertFatal(bwp_Common != NULL, "bwp_Common is null\n");
|
||||
|
||||
NR_BWP_DownlinkDedicated_t *dl_bwp_Dedicated = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1]->bwp_Dedicated;
|
||||
AssertFatal(dl_bwp_Dedicated != NULL, "dl_bwp_Dedicated is null\n");
|
||||
|
||||
NR_SetupRelease_PDCCH_Config_t *pdcch_Config = dl_bwp_Dedicated->pdcch_Config;
|
||||
AssertFatal(pdcch_Config != NULL, "pdcch_Config is null\n");
|
||||
|
||||
NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = bwp_Common->pdcch_ConfigCommon;
|
||||
AssertFatal(pdcch_ConfigCommon != NULL, "pdcch_ConfigCommon is null\n");
|
||||
AssertFatal(pdcch_ConfigCommon->choice.setup->ra_SearchSpace != NULL, "ra_SearchSpace must be available in DL BWP\n");
|
||||
|
||||
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
|
||||
AssertFatal(commonSearchSpaceList != NULL, "commonSearchSpaceList is null\n");
|
||||
AssertFatal(commonSearchSpaceList->list.count > 0, "PDCCH CSS list has 0 elements\n");
|
||||
|
||||
struct NR_PDCCH_Config__controlResourceSetToAddModList *controlResourceSetToAddModList = pdcch_Config->choice.setup->controlResourceSetToAddModList;
|
||||
AssertFatal(controlResourceSetToAddModList != NULL, "controlResourceSetToAddModList is null\n");
|
||||
AssertFatal(controlResourceSetToAddModList->list.count == 1, "controlResourceSetToAddModList->list.count=%d\n", controlResourceSetToAddModList->list.count);
|
||||
AssertFatal(controlResourceSetToAddModList->list.array[0] != NULL, "coreset[0][0] is null\n");
|
||||
|
||||
struct NR_PDCCH_Config__searchSpacesToAddModList *searchSpacesToAddModList = pdcch_Config->choice.setup->searchSpacesToAddModList;
|
||||
AssertFatal(searchSpacesToAddModList != NULL, "searchSpacesToAddModList is null\n");
|
||||
AssertFatal(searchSpacesToAddModList->list.count > 0, "list of UE specifically configured Search Spaces is empty\n");
|
||||
AssertFatal(searchSpacesToAddModList->list.count < FAPI_NR_MAX_SS_PER_CORESET, "too many searchpaces per coreset %d\n", searchSpacesToAddModList->list.count);
|
||||
|
||||
struct NR_UplinkConfig__uplinkBWP_ToAddModList *uplinkBWP_ToAddModList = scd->uplinkConfig->uplinkBWP_ToAddModList;
|
||||
AssertFatal(uplinkBWP_ToAddModList != NULL, "uplinkBWP_ToAddModList is null\n");
|
||||
AssertFatal(uplinkBWP_ToAddModList->list.count == 1, "uplinkBWP_ToAddModList->list->count is %d\n", uplinkBWP_ToAddModList->list.count);
|
||||
|
||||
// check pdcch_Config, pdcch_ConfigCommon and DL BWP
|
||||
mac->DLbwp[0] = scd->downlinkBWP_ToAddModList->list.array[bwp_id - 1];
|
||||
mac->coreset[bwp_id - 1][coreset_id - 1] = controlResourceSetToAddModList->list.array[0];
|
||||
|
||||
// Check dedicated UL BWP and pass to MAC
|
||||
mac->ULbwp[0] = uplinkBWP_ToAddModList->list.array[0];
|
||||
AssertFatal(mac->ULbwp[0]->bwp_Dedicated != NULL, "UL bwp_Dedicated is null\n");
|
||||
|
||||
// check available Search Spaces in the searchSpacesToAddModList and pass to MAC
|
||||
// note: the network configures at most 10 Search Spaces per BWP per cell (including UE-specific and common Search Spaces).
|
||||
for (ss_id = 0; ss_id < searchSpacesToAddModList->list.count; ss_id++) {
|
||||
NR_SearchSpace_t *ss = searchSpacesToAddModList->list.array[ss_id];
|
||||
AssertFatal(ss->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n");
|
||||
AssertFatal(ss->searchSpaceType != NULL, "ss->searchSpaceType is null\n");
|
||||
AssertFatal(*ss->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n");
|
||||
AssertFatal(ss->monitoringSymbolsWithinSlot != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot is null\n");
|
||||
AssertFatal(ss->monitoringSymbolsWithinSlot->buf != NULL, "NR_SearchSpace->monitoringSymbolsWithinSlot->buf is null\n");
|
||||
mac->SSpace[0][0][ss_id] = ss;
|
||||
}
|
||||
|
||||
// Check available CSSs in the commonSearchSpaceList (list of additional common search spaces)
|
||||
// note: commonSearchSpaceList SIZE(1..4)
|
||||
for (int css_id = 0; css_id < commonSearchSpaceList->list.count; css_id++) {
|
||||
NR_SearchSpace_t *css = commonSearchSpaceList->list.array[css_id];
|
||||
AssertFatal(css->controlResourceSetId != NULL, "ss->controlResourceSetId is null\n");
|
||||
AssertFatal(*css->controlResourceSetId == mac->coreset[bwp_id - 1][coreset_id - 1]->controlResourceSetId, "ss->controlResourceSetId is unknown\n");
|
||||
AssertFatal(css->searchSpaceId != 0, "css->searchSpaceId is 0\n");
|
||||
AssertFatal(css->searchSpaceType != NULL, "css->searchSpaceType is null\n");
|
||||
AssertFatal(css->monitoringSymbolsWithinSlot != NULL, "css->monitoringSymbolsWithinSlot is null\n");
|
||||
AssertFatal(css->monitoringSymbolsWithinSlot->buf != NULL, "css->monitoringSymbolsWithinSlot->buf is null\n");
|
||||
mac->SSpace[0][0][ss_id] = css;
|
||||
ss_id++;
|
||||
}
|
||||
}
|
||||
|
||||
int nr_rrc_mac_config_req_ue(
|
||||
module_id_t module_id,
|
||||
int cc_idP,
|
||||
@@ -338,16 +415,16 @@ int nr_rrc_mac_config_req_ue(
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
// NR_ServingCellConfig_t *serving_cell_config = spcell_configP->spCellConfigDedicated;
|
||||
// TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc.
|
||||
|
||||
|
||||
if(mibP != NULL){
|
||||
mac->mib = mibP; // update by every reception
|
||||
}
|
||||
|
||||
if(cell_group_config != NULL ){
|
||||
mac->scg = cell_group_config;
|
||||
mac->servCellIndex = *cell_group_config->spCellConfig->servCellIndex;
|
||||
config_control_ue(mac);
|
||||
if (cell_group_config->spCellConfig->reconfigurationWithSync) {
|
||||
mac->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink;
|
||||
mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
|
||||
@@ -355,7 +432,6 @@ int nr_rrc_mac_config_req_ue(
|
||||
mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity;
|
||||
LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti);
|
||||
}
|
||||
mac->scg = cell_group_config;
|
||||
|
||||
/*
|
||||
if(mac_cell_group_configP != NULL){
|
||||
@@ -420,8 +496,8 @@ int nr_rrc_mac_config_req_ue(
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -178,7 +178,6 @@ typedef struct {
|
||||
SFN_C_TYPE type0_pdcch_ss_sfn_c;
|
||||
uint32_t type0_pdcch_ss_n_c;
|
||||
uint32_t type0_pdcch_consecutive_slots;
|
||||
int rnti_type;
|
||||
|
||||
/* PDUs */
|
||||
/// Outgoing CCCH pdu for PHY
|
||||
@@ -222,11 +221,6 @@ typedef struct {
|
||||
uint32_t RA_tx_frame;
|
||||
/// Random-access variable for window calculation (subframe of last change in window counter)
|
||||
uint8_t RA_tx_subframe;
|
||||
/// Scheduled RX frame for RA Msg2
|
||||
uint16_t msg2_rx_frame;
|
||||
/// Scheduled RX slot for RA Msg2
|
||||
uint16_t msg2_rx_slot;
|
||||
/// Random-access Group B maximum path-loss
|
||||
/// Random-access variable for backoff (frame of last change in backoff counter)
|
||||
uint32_t RA_backoff_frame;
|
||||
/// Random-access variable for backoff (subframe of last change in backoff counter)
|
||||
|
||||
@@ -62,9 +62,8 @@
|
||||
#include "NR_MAC_COMMON/nr_mac.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_proto.h"
|
||||
|
||||
extern int64_t table_6_3_3_2_2_prachConfig_Index [256][9];
|
||||
extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9];
|
||||
extern const uint16_t nr_slots_per_frame[5];
|
||||
extern const uint8_t nr_slots_per_frame[5];
|
||||
|
||||
//extern uint8_t nfapi_mode;
|
||||
|
||||
@@ -360,11 +359,11 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
|
||||
uint8_t sdu_lcids[NB_RB_MAX] = {0};
|
||||
uint16_t sdu_lengths[NB_RB_MAX] = {0};
|
||||
int TBS_bytes = 848, header_length_total, num_sdus, offset, preambleTransMax, mac_ce_len;
|
||||
int TBS_bytes = 848, header_length_total=0, num_sdus, offset, preambleTransMax, mac_ce_len;
|
||||
|
||||
AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n");
|
||||
|
||||
if (UE_mode == PRACH && prach_resources->init_msg1) {
|
||||
if (UE_mode < PUSCH && prach_resources->init_msg1) {
|
||||
|
||||
LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active);
|
||||
|
||||
@@ -449,7 +448,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
nr_get_RA_window(mac);
|
||||
|
||||
// Fill in preamble and PRACH resources
|
||||
if (mac->generate_nr_prach)
|
||||
if (mac->generate_nr_prach == 1)
|
||||
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated);
|
||||
|
||||
offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer
|
||||
@@ -471,7 +470,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
payload[offset + j] = 0; // mac_pdu[offset + j] = 0;
|
||||
}
|
||||
}
|
||||
} else { // RACH is active
|
||||
} else if (mac->RA_window_cnt != -1) { // RACH is active
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
/////* Random Access Response reception (5.1.4 TS 38.321) */////
|
||||
@@ -482,7 +481,6 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
// - handle beam failure recovery request
|
||||
// - handle DL assignment on PDCCH for RA-RNTI
|
||||
// - handle backoff and raResponseWindow params
|
||||
// - disabled contention resolution as OAI NSA is contention-free based
|
||||
|
||||
// LOG_D(MAC, "[MAC][UE %d][RAPROC] frame %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n",
|
||||
// mod_id, frame, nr_tti_tx, mac->RA_window_cnt, mac->RA_tx_frame, mac->RA_tx_subframe);
|
||||
@@ -495,12 +493,13 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
|
||||
if (mac->RA_window_cnt >= 0 && mac->RA_RAPID_found == 1) {
|
||||
|
||||
// mac->ra_state = WAIT_CONTENTION_RESOLUTION;
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR successfully received \n", mod_id, frame, nr_tti_tx);
|
||||
mac->RA_window_cnt = -1;
|
||||
mac->ra_state = RA_SUCCEEDED;
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR successfully received \n", mod_id, frame, nr_tti_tx);
|
||||
|
||||
} else if (mac->RA_window_cnt == 0 && !mac->RA_RAPID_found) {
|
||||
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR reception failed \n", mod_id, frame, nr_tti_tx);
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception failed \n", mod_id, frame, nr_tti_tx);
|
||||
|
||||
mac->ra_state = RA_UE_IDLE;
|
||||
mac->RA_PREAMBLE_TRANSMISSION_COUNTER++;
|
||||
@@ -572,21 +571,21 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
|
||||
// mac->RA_tx_subframe = nr_tti_tx;
|
||||
|
||||
// Fill in preamble and PRACH resources
|
||||
if (mac->generate_nr_prach)
|
||||
if (mac->generate_nr_prach == 1)
|
||||
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
|
||||
|
||||
} else {
|
||||
|
||||
mac->RA_window_cnt--;
|
||||
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR reception not successful, (RA window count %d) \n",
|
||||
LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception not successful, (RA window count %d) \n",
|
||||
mod_id,
|
||||
frame,
|
||||
nr_tti_tx,
|
||||
mac->RA_window_cnt);
|
||||
|
||||
// Fill in preamble and PRACH resources
|
||||
if (mac->generate_nr_prach)
|
||||
if (mac->generate_nr_prach == 1)
|
||||
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
|
||||
|
||||
}
|
||||
@@ -616,28 +615,28 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac){
|
||||
mac->RA_window_cnt = mac->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB
|
||||
|
||||
switch (ra_ResponseWindow) {
|
||||
case 0:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
|
||||
mac->RA_window_cnt += 1;
|
||||
break;
|
||||
case 1:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
|
||||
mac->RA_window_cnt += 2;
|
||||
break;
|
||||
case 2:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
|
||||
mac->RA_window_cnt += 4;
|
||||
break;
|
||||
case 3:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
|
||||
mac->RA_window_cnt += 8;
|
||||
break;
|
||||
case 4:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
|
||||
mac->RA_window_cnt += 10;
|
||||
break;
|
||||
case 5:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
|
||||
mac->RA_window_cnt += 20;
|
||||
break;
|
||||
case 6:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
|
||||
mac->RA_window_cnt += 40;
|
||||
break;
|
||||
case 7:
|
||||
case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
|
||||
mac->RA_window_cnt += 80;
|
||||
break;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user