Merge remote-tracking branch 'origin/develop' into develop-NR_SA_F1AP_5GRECORDS
# Conflicts: # openair1/SCHED_NR_UE/phy_procedures_nr_ue.c # openair2/GNB_APP/MACRLC_nr_paramdef.h # openair2/LAYER2/NR_MAC_gNB/config.c # openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c # openair2/NR_PHY_INTERFACE/NR_IF_Module.c
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
echo "gNB will be started automatically..."
|
||||||
|
sleep 1
|
||||||
|
sudo .././cmake_targets/ran_build/build/nr-softmodem -E -O ../targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
|
||||||
|
done
|
||||||
@@ -230,6 +230,7 @@ MACRLCs = (
|
|||||||
num_cc = 1;
|
num_cc = 1;
|
||||||
tr_s_preference = "local_L1";
|
tr_s_preference = "local_L1";
|
||||||
tr_n_preference = "local_RRC";
|
tr_n_preference = "local_RRC";
|
||||||
|
ulsch_max_slots_inactivity = 1;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ MACRLCs = (
|
|||||||
num_cc = 1;
|
num_cc = 1;
|
||||||
tr_s_preference = "local_L1";
|
tr_s_preference = "local_L1";
|
||||||
tr_n_preference = "local_RRC";
|
tr_n_preference = "local_RRC";
|
||||||
|
ulsch_max_slots_inactivity = 1;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#this is a configuration file
|
||||||
|
#used to build real time processing statistics
|
||||||
|
#for 5G NR phy test (gNB terminate)
|
||||||
|
Title : Processing Time (us)
|
||||||
|
ColNames :
|
||||||
|
- Metric
|
||||||
|
- Average
|
||||||
|
- Max
|
||||||
|
- Average vs Reference Deviation (Reference Value ; Acceptability Threshold)
|
||||||
|
Ref :
|
||||||
|
feprx : 60.0
|
||||||
|
feptx_prec : 8.0
|
||||||
|
feptx_ofdm : 85.0
|
||||||
|
feptx_total : 75.0
|
||||||
|
L1 Tx processing : 300.0
|
||||||
|
DLSCH encoding : 230.0
|
||||||
|
L1 Rx processing : 175.0
|
||||||
|
PUSCH inner-receiver : 100.0
|
||||||
|
PUSCH decoding : 140.0
|
||||||
|
DL & UL scheduling timing stats : 15.0
|
||||||
|
UL Indication : 20.0
|
||||||
|
Threshold :
|
||||||
|
feprx : 1.25
|
||||||
|
feptx_prec : 1.25
|
||||||
|
feptx_ofdm : 1.25
|
||||||
|
feptx_total : 1.25
|
||||||
|
L1 Tx processing : 1.25
|
||||||
|
DLSCH encoding : 1.25
|
||||||
|
L1 Rx processing : 1.25
|
||||||
|
PUSCH inner-receiver : 1.25
|
||||||
|
PUSCH decoding : 1.25
|
||||||
|
DL & UL scheduling timing stats : 1.25
|
||||||
|
UL Indication : 1.25
|
||||||
@@ -453,6 +453,37 @@ class HTMLManagement():
|
|||||||
self.htmlFile.write(' </tr>\n')
|
self.htmlFile.write(' </tr>\n')
|
||||||
self.htmlFile.close()
|
self.htmlFile.close()
|
||||||
|
|
||||||
|
#for the moment it is limited to 4 columns, to be made generic later
|
||||||
|
def CreateHtmlDataLogTable(self, DataLog):
|
||||||
|
if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
|
||||||
|
return
|
||||||
|
self.htmlFile = open('test_results.html', 'a')
|
||||||
|
|
||||||
|
# TabHeader
|
||||||
|
self.htmlFile.write(' <tr bgcolor = "#F0F0F0" >\n')
|
||||||
|
self.htmlFile.write(' <td colspan=' + str(5+self.htmlUEConnected) + '><b> ---- ' + DataLog['Title'] + ' ---- </b></td>\n')
|
||||||
|
self.htmlFile.write(' </tr>\n')
|
||||||
|
self.htmlFile.write(' <tr bgcolor = "#33CCFF" >\n')
|
||||||
|
self.htmlFile.write(' <th colspan="3">'+ DataLog['ColNames'][0] +'</th>\n')
|
||||||
|
self.htmlFile.write(' <th>' + DataLog['ColNames'][1] + '</th>\n')
|
||||||
|
self.htmlFile.write(' <th>' + DataLog['ColNames'][2] + '</th>\n')
|
||||||
|
self.htmlFile.write(' <th colspan=' + str(1+self.htmlUEConnected) + '>'+ DataLog['ColNames'][3] +'</th>\n')
|
||||||
|
self.htmlFile.write(' </tr>\n')
|
||||||
|
|
||||||
|
for k in DataLog['Data']:
|
||||||
|
# TestRow
|
||||||
|
self.htmlFile.write(' <tr>\n')
|
||||||
|
self.htmlFile.write(' <td colspan="3" bgcolor = "lightcyan" >' + k + ' </td>\n')
|
||||||
|
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + DataLog['Data'][k][0] + ' </td>\n')
|
||||||
|
self.htmlFile.write(' <td bgcolor = "lightcyan" >' + DataLog['Data'][k][1] + ' </td>\n')
|
||||||
|
if float(DataLog['Data'][k][2])> DataLog['Threshold'][k]:
|
||||||
|
self.htmlFile.write(' <th bgcolor = "red" >' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '</th>\n')
|
||||||
|
else:
|
||||||
|
self.htmlFile.write(' <th bgcolor = "green" ><font color="white">' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '</th>\n')
|
||||||
|
self.htmlFile.write(' </tr>\n')
|
||||||
|
self.htmlFile.close()
|
||||||
|
|
||||||
|
|
||||||
def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue):
|
def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue):
|
||||||
if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
|
if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
|
||||||
self.htmlFile = open('test_results.html', 'a')
|
self.htmlFile = open('test_results.html', 'a')
|
||||||
|
|||||||
+41
-11
@@ -37,6 +37,8 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from multiprocessing import Process, Lock, SimpleQueue
|
from multiprocessing import Process, Lock, SimpleQueue
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
#-----------------------------------------------------------
|
#-----------------------------------------------------------
|
||||||
# OAI Testing modules
|
# OAI Testing modules
|
||||||
@@ -90,6 +92,7 @@ class RANManagement():
|
|||||||
self.testCase_id = ''
|
self.testCase_id = ''
|
||||||
self.epcPcapFile = ''
|
self.epcPcapFile = ''
|
||||||
self.runtime_stats= ''
|
self.runtime_stats= ''
|
||||||
|
self.datalog_rt_stats={}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -633,6 +636,8 @@ class RANManagement():
|
|||||||
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
||||||
else:
|
else:
|
||||||
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
|
||||||
|
if len(self.datalog_rt_stats)!=0:
|
||||||
|
HTML.CreateHtmlDataLogTable(self.datalog_rt_stats)
|
||||||
self.eNBmbmsEnables[int(self.eNB_instance)] = False
|
self.eNBmbmsEnables[int(self.eNB_instance)] = False
|
||||||
self.eNBstatuses[int(self.eNB_instance)] = -1
|
self.eNBstatuses[int(self.eNB_instance)] = -1
|
||||||
|
|
||||||
@@ -699,6 +704,21 @@ class RANManagement():
|
|||||||
#count "problem receiving samples" msg
|
#count "problem receiving samples" msg
|
||||||
pb_receiving_samples_cnt = 0
|
pb_receiving_samples_cnt = 0
|
||||||
|
|
||||||
|
#the datalog config file has to be loaded
|
||||||
|
datalog_rt_stats_file='datalog_rt_stats.yaml'
|
||||||
|
if (os.path.isfile(datalog_rt_stats_file)):
|
||||||
|
yaml_file=datalog_rt_stats_file
|
||||||
|
elif (os.path.isfile('ci-scripts/'+datalog_rt_stats_file)):
|
||||||
|
yaml_file='ci-scripts/'+datalog_rt_stats_file
|
||||||
|
else:
|
||||||
|
logging.error("Datalog RT stats yaml file cannot be found")
|
||||||
|
sys.exit("Datalog RT stats yaml file cannot be found")
|
||||||
|
|
||||||
|
with open(yaml_file,'r') as f:
|
||||||
|
datalog_rt_stats = yaml.load(f,Loader=yaml.FullLoader)
|
||||||
|
rt_keys = datalog_rt_stats['Ref'] #we use the keys from the Ref field
|
||||||
|
|
||||||
|
|
||||||
for line in enb_log_file.readlines():
|
for line in enb_log_file.readlines():
|
||||||
# Runtime statistics
|
# Runtime statistics
|
||||||
result = re.search('Run time:' ,str(line))
|
result = re.search('Run time:' ,str(line))
|
||||||
@@ -857,21 +877,21 @@ class RANManagement():
|
|||||||
#keys below are the markers we are loooking for, loop over this keys list
|
#keys below are the markers we are loooking for, loop over this keys list
|
||||||
#everytime these markers are found in the log file, the previous ones are overwritten in the dict
|
#everytime these markers are found in the log file, the previous ones are overwritten in the dict
|
||||||
#eventually we record and print only the last occurence
|
#eventually we record and print only the last occurence
|
||||||
keys = {'UE ID','dlsch_rounds','dlsch_total_bytes','ulsch_rounds','ulsch_total_bytes_scheduled', 'scheduling timing stats'}
|
keys = {'UE ID','dlsch_rounds','dlsch_total_bytes','ulsch_rounds','ulsch_total_bytes_scheduled'}
|
||||||
for k in keys:
|
for k in keys:
|
||||||
result = re.search(k, line)
|
result = re.search(k, line)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
#remove 1- all useless char before relevant info (ulsch or dlsch) 2- trailing char
|
#remove 1- all useless char before relevant info (ulsch or dlsch) 2- trailing char
|
||||||
dlsch_ulsch_stats[k]=re.sub(r'^.*\]\s+', r'' , line.rstrip())
|
dlsch_ulsch_stats[k]=re.sub(r'^.*\]\s+', r'' , line.rstrip())
|
||||||
#real time statistics
|
#real time statistics for gNB
|
||||||
#same method as above
|
for k in rt_keys:
|
||||||
keys = {'feprx','feptx_prec','feptx_ofdm','feptx_total','L1 Tx processing','DLSCH encoding','L1 Rx processing','PUSCH inner-receiver','PUSCH decoding'}
|
|
||||||
for k in keys:
|
|
||||||
result = re.search(k, line)
|
result = re.search(k, line)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
#remove 1- all useless char before relevant info 2- trailing char
|
#remove 1- all useless char before relevant info 2- trailing char
|
||||||
|
line=line.replace('[0m','')
|
||||||
tmp=re.match(rf'^.*?(\b{k}\b.*)',line.rstrip()) #from python 3.6 we can use literal string interpolation for the variable k, using rf' in the regex
|
tmp=re.match(rf'^.*?(\b{k}\b.*)',line.rstrip()) #from python 3.6 we can use literal string interpolation for the variable k, using rf' in the regex
|
||||||
real_time_stats[k]=tmp.group(1)
|
real_time_stats[k]=tmp.group(1)
|
||||||
|
|
||||||
#count "problem receiving samples" msg
|
#count "problem receiving samples" msg
|
||||||
result = re.search('\[PHY\]\s+problem receiving samples', str(line))
|
result = re.search('\[PHY\]\s+problem receiving samples', str(line))
|
||||||
if result is not None:
|
if result is not None:
|
||||||
@@ -920,13 +940,23 @@ class RANManagement():
|
|||||||
logging.debug(dlsch_ulsch_stats[key])
|
logging.debug(dlsch_ulsch_stats[key])
|
||||||
htmleNBFailureMsg += statMsg
|
htmleNBFailureMsg += statMsg
|
||||||
|
|
||||||
#real time statistics statistics
|
#real time statistics
|
||||||
|
datalog_rt_stats['Data']={}
|
||||||
if len(real_time_stats)!=0: #check if dictionary is not empty
|
if len(real_time_stats)!=0: #check if dictionary is not empty
|
||||||
statMsg=''
|
for k in real_time_stats:
|
||||||
for key in real_time_stats: #for each dictionary key
|
tmp=re.match(r'^(?P<metric>.*):\s+(?P<avg>\d+\.\d+) us;\s+\d+;\s+(?P<max>\d+\.\d+) us;',real_time_stats[k])
|
||||||
statMsg += real_time_stats[key] + '\n'
|
if tmp is not None:
|
||||||
logging.debug(real_time_stats[key])
|
metric=tmp.group('metric')
|
||||||
htmleNBFailureMsg += statMsg
|
avg=float(tmp.group('avg'))
|
||||||
|
max=float(tmp.group('max'))
|
||||||
|
datalog_rt_stats['Data'][metric]=["{:.0f}".format(avg),"{:.0f}".format(max),"{:.2f}".format(avg/datalog_rt_stats['Ref'][metric])]
|
||||||
|
#once all metrics are collected, store the data as a class attribute to build a dedicated HTML table afterward
|
||||||
|
self.datalog_rt_stats=datalog_rt_stats
|
||||||
|
#check if there is a fail => will render the test as failed
|
||||||
|
for k in datalog_rt_stats['Data']:
|
||||||
|
if float(datalog_rt_stats['Data'][k][2])> datalog_rt_stats['Threshold'][k]: #condition for fail : avg/ref is greater than the fixed threshold
|
||||||
|
#setting prematureExit is ok although not the best option
|
||||||
|
self.prematureExit=True
|
||||||
else:
|
else:
|
||||||
statMsg = 'No real time stats found in the log file\n'
|
statMsg = 'No real time stats found in the log file\n'
|
||||||
logging.debug('No real time stats found in the log file')
|
logging.debug('No real time stats found in the log file')
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<htmlTabRef>gNB-PHY-Test</htmlTabRef>
|
<htmlTabRef>gNB-PHY-Test</htmlTabRef>
|
||||||
<htmlTabName>Run-gNB-PHY-Test</htmlTabName>
|
<htmlTabName>Run-gNB-PHY-Test</htmlTabName>
|
||||||
<htmlTabIcon>tasks</htmlTabIcon>
|
<htmlTabIcon>tasks</htmlTabIcon>
|
||||||
<repeatCount>2</repeatCount>
|
<repeatCount>3</repeatCount>
|
||||||
<TestCaseRequestedList>
|
<TestCaseRequestedList>
|
||||||
090101 000001 090109
|
090101 000001 090109
|
||||||
</TestCaseRequestedList>
|
</TestCaseRequestedList>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
<testCase id="000001">
|
<testCase id="000001">
|
||||||
<class>IdleSleep</class>
|
<class>IdleSleep</class>
|
||||||
<desc>Sleep</desc>
|
<desc>Sleep</desc>
|
||||||
<idle_sleep_time_in_sec>180</idle_sleep_time_in_sec>
|
<idle_sleep_time_in_sec>300</idle_sleep_time_in_sec>
|
||||||
</testCase>
|
</testCase>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -553,7 +553,7 @@ void *UE_thread(void *arg) {
|
|||||||
if (UE->is_synchronized) {
|
if (UE->is_synchronized) {
|
||||||
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
|
decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx);
|
||||||
// shift the frame index with all the frames we trashed meanwhile we perform the synch search
|
// shift the frame index with all the frames we trashed meanwhile we perform the synch search
|
||||||
decoded_frame_rx=(decoded_frame_rx + (!UE->init_sync_frame) + trashed_frames) % MAX_FRAME_NUMBER;
|
decoded_frame_rx=(decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER;
|
||||||
}
|
}
|
||||||
delNotifiedFIFO_elt(res);
|
delNotifiedFIFO_elt(res);
|
||||||
start_rx_stream=0;
|
start_rx_stream=0;
|
||||||
@@ -693,9 +693,9 @@ void *UE_thread(void *arg) {
|
|||||||
pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
|
pushNotifiedFIFO_nothreadSafe(&freeBlocks,res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( decoded_frame_rx>0 && decoded_frame_rx != curMsg->proc.frame_rx)
|
if (decoded_frame_rx>0 && decoded_frame_rx != curMsg->proc.frame_rx)
|
||||||
LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n",
|
LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n",
|
||||||
decoded_frame_rx, curMsg->proc.frame_rx );
|
decoded_frame_rx, curMsg->proc.frame_rx);
|
||||||
|
|
||||||
// use previous timing_advance value to compute writeTimestamp
|
// use previous timing_advance value to compute writeTimestamp
|
||||||
writeTimestamp = timestamp+
|
writeTimestamp = timestamp+
|
||||||
|
|||||||
@@ -308,12 +308,15 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames)
|
|||||||
// every 7*(1<<mu) symbols there is a different prefix length (38.211 5.3.1)
|
// every 7*(1<<mu) symbols there is a different prefix length (38.211 5.3.1)
|
||||||
int n_symb_prefix0 = (ue->symbol_offset/(7*(1<<mu)))+1;
|
int n_symb_prefix0 = (ue->symbol_offset/(7*(1<<mu)))+1;
|
||||||
sync_pos_frame = n_symb_prefix0*(fp->ofdm_symbol_size + fp->nb_prefix_samples0)+(ue->symbol_offset-n_symb_prefix0)*(fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
sync_pos_frame = n_symb_prefix0*(fp->ofdm_symbol_size + fp->nb_prefix_samples0)+(ue->symbol_offset-n_symb_prefix0)*(fp->ofdm_symbol_size + fp->nb_prefix_samples);
|
||||||
if (ue->ssb_offset < sync_pos_frame)
|
// for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of the n_frames we got sync
|
||||||
|
ue->init_sync_frame = n_frames - 1 - is;
|
||||||
|
// we also need to take into account the shift by samples_per_frame in case the if is true
|
||||||
|
if (ue->ssb_offset < sync_pos_frame){
|
||||||
ue->rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset;
|
ue->rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset;
|
||||||
|
ue->init_sync_frame += 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ue->rx_offset = ue->ssb_offset - sync_pos_frame;
|
ue->rx_offset = ue->ssb_offset - sync_pos_frame;
|
||||||
|
|
||||||
ue->init_sync_frame = is;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -589,7 +589,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
|
|||||||
frame_parms->ssb_index += (((nr_ue_pbch_vars->xtra_byte>>(7-i))&0x01)<<(3+i));
|
frame_parms->ssb_index += (((nr_ue_pbch_vars->xtra_byte>>(7-i))&0x01)<<(3+i));
|
||||||
}
|
}
|
||||||
|
|
||||||
ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms,i_ssb);
|
ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms,frame_parms->ssb_index);
|
||||||
if (frame_parms->half_frame_bit)
|
if (frame_parms->half_frame_bit)
|
||||||
ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot;
|
ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot;
|
||||||
|
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ void nr_ue_pbch_procedures(uint8_t gNB_id,
|
|||||||
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN);
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN);
|
||||||
|
|
||||||
LOG_D(PHY,"[UE %d] Frame %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,ue->frame_parms.Nid_cell,gNB_id);
|
LOG_D(PHY,"[UE %d] Frame %d Slot %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,nr_slot_rx,ue->frame_parms.Nid_cell,gNB_id);
|
||||||
|
|
||||||
ret = nr_rx_pbch(ue, proc,
|
ret = nr_rx_pbch(ue, proc,
|
||||||
ue->pbch_vars[gNB_id],
|
ue->pbch_vars[gNB_id],
|
||||||
|
|||||||
@@ -742,13 +742,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
prepare_scd(scd);
|
prepare_scd(scd);
|
||||||
|
|
||||||
fill_default_secondaryCellGroup(scc,
|
fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0);
|
||||||
scd,
|
|
||||||
secondaryCellGroup,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
n_tx,
|
|
||||||
0);
|
|
||||||
|
|
||||||
/* RRC parameter validation for secondaryCellGroup */
|
/* RRC parameter validation for secondaryCellGroup */
|
||||||
fix_scd(scd);
|
fix_scd(scd);
|
||||||
|
|||||||
@@ -686,13 +686,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
prepare_scd(scd);
|
prepare_scd(scd);
|
||||||
|
|
||||||
fill_default_secondaryCellGroup(scc,
|
fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0);
|
||||||
scd,
|
|
||||||
secondaryCellGroup,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
n_tx,
|
|
||||||
0);
|
|
||||||
|
|
||||||
// xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
|
// xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
#define CONFIG_STRING_MACRLC_REMOTE_S_PORTC "remote_s_portc"
|
#define CONFIG_STRING_MACRLC_REMOTE_S_PORTC "remote_s_portc"
|
||||||
#define CONFIG_STRING_MACRLC_LOCAL_S_PORTD "local_s_portd"
|
#define CONFIG_STRING_MACRLC_LOCAL_S_PORTD "local_s_portd"
|
||||||
#define CONFIG_STRING_MACRLC_REMOTE_S_PORTD "remote_s_portd"
|
#define CONFIG_STRING_MACRLC_REMOTE_S_PORTD "remote_s_portd"
|
||||||
|
#define CONFIG_STRING_MACRLC_ULSCH_MAX_SLOTS_INACTIVITY "ulsch_max_slots_inactivity"
|
||||||
#define CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10 "pusch_TargetSNRx10"
|
#define CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10 "pusch_TargetSNRx10"
|
||||||
#define CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10 "pucch_TargetSNRx10"
|
#define CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10 "pucch_TargetSNRx10"
|
||||||
#define CONFIG_STRING_MACRLC_PUCCHFAILURETHRES "pucch_FailureThres"
|
#define CONFIG_STRING_MACRLC_PUCCHFAILURETHRES "pucch_FailureThres"
|
||||||
@@ -82,6 +83,7 @@
|
|||||||
{CONFIG_STRING_MACRLC_REMOTE_S_PORTC, NULL, 0, uptr:NULL, defintval:50020, TYPE_UINT, 0}, \
|
{CONFIG_STRING_MACRLC_REMOTE_S_PORTC, NULL, 0, uptr:NULL, defintval:50020, TYPE_UINT, 0}, \
|
||||||
{CONFIG_STRING_MACRLC_LOCAL_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \
|
{CONFIG_STRING_MACRLC_LOCAL_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \
|
||||||
{CONFIG_STRING_MACRLC_REMOTE_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \
|
{CONFIG_STRING_MACRLC_REMOTE_S_PORTD, NULL, 0, uptr:NULL, defintval:50021, TYPE_UINT, 0}, \
|
||||||
|
{CONFIG_STRING_MACRLC_ULSCH_MAX_SLOTS_INACTIVITY, "Maximum number of slots before a UE is scheduled ULSCH due to inactivity", 0, uptr:NULL, defintval:200, TYPE_UINT, 0}, \
|
||||||
{CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \
|
{CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \
|
||||||
{CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:150, TYPE_INT, 0}, \
|
{CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:150, TYPE_INT, 0}, \
|
||||||
{CONFIG_STRING_MACRLC_PUCCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \
|
{CONFIG_STRING_MACRLC_PUCCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \
|
||||||
@@ -104,6 +106,7 @@
|
|||||||
#define MACRLC_REMOTE_S_PORTC_IDX 14
|
#define MACRLC_REMOTE_S_PORTC_IDX 14
|
||||||
#define MACRLC_LOCAL_S_PORTD_IDX 15
|
#define MACRLC_LOCAL_S_PORTD_IDX 15
|
||||||
#define MACRLC_REMOTE_S_PORTD_IDX 16
|
#define MACRLC_REMOTE_S_PORTD_IDX 16
|
||||||
|
#define MACRLC_ULSCH_MAX_SLOTS_INACTIVITY 17
|
||||||
#define MACRLC_PUSCHTARGETSNRX10_IDX 17
|
#define MACRLC_PUSCHTARGETSNRX10_IDX 17
|
||||||
#define MACRLC_PUCCHTARGETSNRX10_IDX 18
|
#define MACRLC_PUCCHTARGETSNRX10_IDX 18
|
||||||
#define MACRLC_PUCCHFAILURETHRES_IDX 19
|
#define MACRLC_PUCCHFAILURETHRES_IDX 19
|
||||||
|
|||||||
@@ -723,6 +723,7 @@ void RCconfig_nr_macrlc() {
|
|||||||
}else { // other midhaul
|
}else { // other midhaul
|
||||||
AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr));
|
AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr));
|
||||||
}
|
}
|
||||||
|
RC.nrmac[j]->ulsch_max_slots_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_SLOTS_INACTIVITY].uptr);
|
||||||
}// for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
}// for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
||||||
}else {// MacRLC_ParamList.numelt > 0
|
}else {// MacRLC_ParamList.numelt > 0
|
||||||
printf("No %s configuration found \n", CONFIG_STRING_MACRLC_LIST);
|
printf("No %s configuration found \n", CONFIG_STRING_MACRLC_LIST);
|
||||||
|
|||||||
@@ -370,14 +370,6 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
|
|||||||
AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL,
|
AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL,
|
||||||
"could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n");
|
"could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n");
|
||||||
|
|
||||||
for (int i = 0; i < MAX_NUM_BWP; ++i) {
|
|
||||||
RC.nrmac[Mod_idP]->pucch_index_used[i] =
|
|
||||||
calloc(n, sizeof(*RC.nrmac[Mod_idP]->pucch_index_used));
|
|
||||||
AssertFatal(RC.nrmac[Mod_idP]->pucch_index_used[i],
|
|
||||||
"could not allocate memory for RC.nrmac[]->pucch_index_used[%d]\n",
|
|
||||||
i);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_I(NR_MAC,"Configuring common parameters from NR ServingCellConfig\n");
|
LOG_I(NR_MAC,"Configuring common parameters from NR ServingCellConfig\n");
|
||||||
|
|
||||||
config_common(Mod_idP,
|
config_common(Mod_idP,
|
||||||
|
|||||||
@@ -402,7 +402,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This schedule SR
|
// This schedule SR
|
||||||
// TODO
|
nr_sr_reporting(module_idP, frame, slot);
|
||||||
|
|
||||||
// Schedule CSI measurement reporting: check in slot 0 for the whole frame
|
// Schedule CSI measurement reporting: check in slot 0 for the whole frame
|
||||||
if (slot == 0)
|
if (slot == 0)
|
||||||
|
|||||||
@@ -252,8 +252,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
|
|||||||
case 3:
|
case 3:
|
||||||
// long bitmap FR2 max 64 SSBs
|
// long bitmap FR2 max 64 SSBs
|
||||||
num_ssb = 0;
|
num_ssb = 0;
|
||||||
for (int i_ssb=0; i_ssb<63; i_ssb++) {
|
for (int i_ssb=0; i_ssb<64; i_ssb++) {
|
||||||
if ((longBitmap->buf[i_ssb/8]>>(7-i_ssb))&0x01) {
|
if ((longBitmap->buf[i_ssb/8]>>(7-(i_ssb%8)))&0x01) {
|
||||||
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
|
ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb);
|
||||||
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
|
// if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters
|
||||||
if ((ssb_start_symbol/14) == rel_slot){
|
if ((ssb_start_symbol/14) == rel_slot){
|
||||||
|
|||||||
@@ -120,8 +120,13 @@ int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = {
|
|||||||
|
|
||||||
void nr_schedule_pucch(int Mod_idP,
|
void nr_schedule_pucch(int Mod_idP,
|
||||||
frame_t frameP,
|
frame_t frameP,
|
||||||
sub_frame_t slotP) {
|
sub_frame_t slotP)
|
||||||
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
|
{
|
||||||
|
gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP];
|
||||||
|
if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slotP / 64], slotP))
|
||||||
|
return;
|
||||||
|
|
||||||
|
NR_UE_info_t *UE_info = &nrmac->UE_info;
|
||||||
const NR_list_t *UE_list = &UE_info->list;
|
const NR_list_t *UE_list = &UE_info->list;
|
||||||
|
|
||||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||||
@@ -508,11 +513,11 @@ void nr_csi_meas_reporting(int Mod_idP,
|
|||||||
|
|
||||||
// find free PUCCH that is in order with possibly existing PUCCH
|
// find free PUCCH that is in order with possibly existing PUCCH
|
||||||
// schedulings (other CSI, SR)
|
// schedulings (other CSI, SR)
|
||||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[2];
|
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[1];
|
||||||
AssertFatal(curr_pucch->csi_bits == 0
|
AssertFatal(curr_pucch->csi_bits == 0
|
||||||
&& !curr_pucch->sr_flag
|
&& !curr_pucch->sr_flag
|
||||||
&& curr_pucch->dai_c == 0,
|
&& curr_pucch->dai_c == 0,
|
||||||
"PUCCH not free at index 2 for UE %04x\n",
|
"PUCCH not free at index 1 for UE %04x\n",
|
||||||
UE_info->rnti[UE_id]);
|
UE_info->rnti[UE_id]);
|
||||||
curr_pucch->frame = frame;
|
curr_pucch->frame = frame;
|
||||||
curr_pucch->ul_slot = sched_slot;
|
curr_pucch->ul_slot = sched_slot;
|
||||||
@@ -1011,15 +1016,6 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
|
|||||||
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
|
||||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||||
|
|
||||||
// tpc (power control)
|
|
||||||
if (uci_01->harq->harq_confidence_level == 0)
|
|
||||||
sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10,
|
|
||||||
uci_01->ul_cqi,
|
|
||||||
30);
|
|
||||||
LOG_D(NR_MAC,"pucch tpc %d\n",sched_ctrl->tpc1);
|
|
||||||
|
|
||||||
sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640;
|
|
||||||
|
|
||||||
if (((uci_01->pduBitmap >> 1) & 0x01)) {
|
if (((uci_01->pduBitmap >> 1) & 0x01)) {
|
||||||
// iterate over received harq bits
|
// iterate over received harq bits
|
||||||
for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
|
for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
|
||||||
@@ -1034,6 +1030,20 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
|
|||||||
handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0);
|
handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check scheduling request result, confidence_level == 0 is good
|
||||||
|
if (uci_01->pduBitmap & 0x1 && uci_01->sr->sr_indication && uci_01->sr->sr_confidence_level == 0 && uci_01->ul_cqi >= 148) {
|
||||||
|
// SR detected with SNR >= 10dB
|
||||||
|
sched_ctrl->SR |= true;
|
||||||
|
LOG_D(MAC, "SR UE %04x ul_cqi %d\n", uci_01->rnti, uci_01->ul_cqi);
|
||||||
|
}
|
||||||
|
|
||||||
|
// tpc (power control) only if we received AckNack or positive SR. For a
|
||||||
|
// negative SR, the UE won't have sent anything, and the SNR is not valid
|
||||||
|
if (((uci_01->pduBitmap >> 1) & 0x1) || sched_ctrl->SR) {
|
||||||
|
sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_01->ul_cqi, 30);
|
||||||
|
sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
|
void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
|
||||||
@@ -1113,10 +1123,7 @@ bool nr_acknack_scheduling(int mod_id,
|
|||||||
* * we do not multiplex with CSI, which is always in pucch_sched[2]
|
* * we do not multiplex with CSI, which is always in pucch_sched[2]
|
||||||
* * SR uses format 0 and is allocated in the first UL (mixed) slot (and not
|
* * SR uses format 0 and is allocated in the first UL (mixed) slot (and not
|
||||||
* later)
|
* later)
|
||||||
* * that the PUCCH resource set 0 (for up to 2 bits) points to the first N
|
* * each UE has dedicated PUCCH Format 0 resources, and we use index 0! */
|
||||||
* PUCCH resources, where N is the number of resources in the PUCCH
|
|
||||||
* resource set. This is used in pucch_index_used, which counts the used
|
|
||||||
* resources by index, and not by their ID! */
|
|
||||||
NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[mod_id]->UE_info.UE_sched_ctrl[UE_id];
|
NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[mod_id]->UE_info.UE_sched_ctrl[UE_id];
|
||||||
NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0];
|
NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0];
|
||||||
pucch->r_pucch=r_pucch;
|
pucch->r_pucch=r_pucch;
|
||||||
@@ -1125,12 +1132,8 @@ bool nr_acknack_scheduling(int mod_id,
|
|||||||
__func__,
|
__func__,
|
||||||
pucch->csi_bits);
|
pucch->csi_bits);
|
||||||
|
|
||||||
const int max_acknacks = 2;
|
|
||||||
AssertFatal(pucch->dai_c + pucch->sr_flag <= max_acknacks,
|
|
||||||
"illegal number of bits in PUCCH of UE %d\n",
|
|
||||||
UE_id);
|
|
||||||
/* if the currently allocated PUCCH of this UE is full, allocate it */
|
/* if the currently allocated PUCCH of this UE is full, allocate it */
|
||||||
if (pucch->sr_flag + pucch->dai_c == max_acknacks) {
|
if (pucch->dai_c == 2) {
|
||||||
/* advance the UL slot information in PUCCH by one so we won't schedule in
|
/* advance the UL slot information in PUCCH by one so we won't schedule in
|
||||||
* the same slot again */
|
* the same slot again */
|
||||||
const int f = pucch->frame;
|
const int f = pucch->frame;
|
||||||
@@ -1140,7 +1143,7 @@ bool nr_acknack_scheduling(int mod_id,
|
|||||||
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
|
pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
|
||||||
pucch->ul_slot = (s + 1) % n_slots_frame;
|
pucch->ul_slot = (s + 1) % n_slots_frame;
|
||||||
// we assume that only two indices over the array sched_pucch exist
|
// we assume that only two indices over the array sched_pucch exist
|
||||||
NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[2];
|
NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[1];
|
||||||
// skip the CSI PUCCH if it is present and if in the next frame/slot
|
// skip the CSI PUCCH if it is present and if in the next frame/slot
|
||||||
csi_pucch->r_pucch=-1;
|
csi_pucch->r_pucch=-1;
|
||||||
if (csi_pucch->csi_bits > 0
|
if (csi_pucch->csi_bits > 0
|
||||||
@@ -1153,6 +1156,7 @@ bool nr_acknack_scheduling(int mod_id,
|
|||||||
pucch->ul_slot,
|
pucch->ul_slot,
|
||||||
UE_id);
|
UE_id);
|
||||||
nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
|
nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
|
||||||
|
memset(csi_pucch, 0, sizeof(*csi_pucch));
|
||||||
pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f;
|
pucch->frame = s >= n_slots_frame - 2 ? (f + 1) % 1024 : f;
|
||||||
pucch->ul_slot = (s + 2) % n_slots_frame;
|
pucch->ul_slot = (s + 2) % n_slots_frame;
|
||||||
}
|
}
|
||||||
@@ -1172,9 +1176,8 @@ bool nr_acknack_scheduling(int mod_id,
|
|||||||
uint8_t pdsch_to_harq_feedback[8];
|
uint8_t pdsch_to_harq_feedback[8];
|
||||||
get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback);
|
get_pdsch_to_harq_feedback(mod_id, UE_id, ss_type, pdsch_to_harq_feedback);
|
||||||
|
|
||||||
/* there is a scheduled SR or HARQ. Check whether we can use it for this
|
/* there is a HARQ. Check whether we can use it for this ACKNACK */
|
||||||
* ACKNACK */
|
if (pucch->dai_c > 0) {
|
||||||
if (pucch->sr_flag + pucch->dai_c > 0) {
|
|
||||||
/* this UE already has a PUCCH occasion */
|
/* this UE already has a PUCCH occasion */
|
||||||
DevAssert(pucch->frame == frame);
|
DevAssert(pucch->frame == frame);
|
||||||
|
|
||||||
@@ -1205,34 +1208,14 @@ bool nr_acknack_scheduling(int mod_id,
|
|||||||
|
|
||||||
/* we need to find a new PUCCH occasion */
|
/* we need to find a new PUCCH occasion */
|
||||||
|
|
||||||
NR_PUCCH_Config_t *pucch_Config=NULL;
|
|
||||||
int bwp_Id=0;
|
|
||||||
if (sched_ctrl->active_ubwp) {
|
|
||||||
pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
|
||||||
bwp_Id= sched_ctrl->active_ubwp->bwp_Id;
|
|
||||||
}
|
|
||||||
else if (RC.nrmac[mod_id]->UE_info.CellGroup[UE_id] &&
|
|
||||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig &&
|
|
||||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated &&
|
|
||||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig &&
|
|
||||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP &&
|
|
||||||
RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup)
|
|
||||||
pucch_Config = RC.nrmac[mod_id]->UE_info.CellGroup[UE_id]->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pucch_Config->choice.setup;
|
|
||||||
if (pucch_Config) {
|
|
||||||
DevAssert(pucch_Config->resourceToAddModList->list.count > 0);
|
|
||||||
DevAssert(pucch_Config->resourceSetToAddModList->list.count > 0);
|
|
||||||
}
|
|
||||||
int n_res = (pucch_Config) ?
|
|
||||||
pucch_Config->resourceSetToAddModList->list.array[0]->resourceList.list.count :
|
|
||||||
nr_get_default_pucch_res(*scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon);
|
|
||||||
int *pucch_index_used = RC.nrmac[mod_id]->pucch_index_used[bwp_Id];
|
|
||||||
|
|
||||||
/* if time information is outdated (e.g., last PUCCH occasion in last frame),
|
/* if time information is outdated (e.g., last PUCCH occasion in last frame),
|
||||||
* set to first possible UL occasion in this frame. Note that if such UE is
|
* set to first possible UL occasion in this frame. Note that if such UE is
|
||||||
* scheduled a lot and used all AckNacks, pucch->frame might have been
|
* scheduled a lot and used all AckNacks, pucch->frame might have been
|
||||||
* wrapped around to next frame */
|
* wrapped around to next frame */
|
||||||
if (frame != pucch->frame || pucch->ul_slot < first_ul_slot_tdd) {
|
if (frame != pucch->frame || pucch->ul_slot < first_ul_slot_tdd) {
|
||||||
DevAssert(pucch->sr_flag + pucch->dai_c == 0);
|
AssertFatal(pucch->sr_flag + pucch->dai_c == 0,
|
||||||
|
"expected no SR/AckNack for UE %d in %4d.%2d, but has %d/%d for %4d.%2d\n",
|
||||||
|
UE_id, frame, slot, pucch->sr_flag, pucch->dai_c, pucch->frame, pucch->ul_slot);
|
||||||
AssertFatal(frame + 1 != pucch->frame,
|
AssertFatal(frame + 1 != pucch->frame,
|
||||||
"frame wrap around not handled in %s() yet\n",
|
"frame wrap around not handled in %s() yet\n",
|
||||||
__func__);
|
__func__);
|
||||||
@@ -1240,27 +1223,11 @@ bool nr_acknack_scheduling(int mod_id,
|
|||||||
pucch->ul_slot = first_ul_slot_tdd;
|
pucch->ul_slot = first_ul_slot_tdd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase to first slot in which PUCCH resources are available
|
|
||||||
while (pucch_index_used[pucch->ul_slot] >= n_res) {
|
|
||||||
pucch->ul_slot++;
|
|
||||||
/* if there is no free resource anymore, abort search */
|
|
||||||
if ((pucch->frame == frame
|
|
||||||
&& pucch->ul_slot >= first_ul_slot_tdd + nr_ulmix_slots)
|
|
||||||
|| (pucch->frame == frame + 1)) {
|
|
||||||
LOG_E(MAC,
|
|
||||||
"%4d.%2d no free PUCCH resources anymore while searching for UE %d\n",
|
|
||||||
frame,
|
|
||||||
slot,
|
|
||||||
UE_id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// advance ul_slot if it is not reachable by UE
|
// advance ul_slot if it is not reachable by UE
|
||||||
pucch->ul_slot = max(pucch->ul_slot, slot + pdsch_to_harq_feedback[0]);
|
pucch->ul_slot = max(pucch->ul_slot, slot + pdsch_to_harq_feedback[0]);
|
||||||
|
|
||||||
// is there already CSI in this slot?
|
// is there already CSI in this slot?
|
||||||
const NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[2];
|
NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[1];
|
||||||
// skip the CSI PUCCH if it is present and if in the next frame/slot
|
// skip the CSI PUCCH if it is present and if in the next frame/slot
|
||||||
if (csi_pucch->csi_bits > 0
|
if (csi_pucch->csi_bits > 0
|
||||||
&& csi_pucch->frame == pucch->frame
|
&& csi_pucch->frame == pucch->frame
|
||||||
@@ -1272,6 +1239,7 @@ bool nr_acknack_scheduling(int mod_id,
|
|||||||
pucch->ul_slot,
|
pucch->ul_slot,
|
||||||
UE_id);
|
UE_id);
|
||||||
nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
|
nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
|
||||||
|
memset(csi_pucch, 0, sizeof(*csi_pucch));
|
||||||
/* advance the UL slot information in PUCCH by one so we won't schedule in
|
/* advance the UL slot information in PUCCH by one so we won't schedule in
|
||||||
* the same slot again */
|
* the same slot again */
|
||||||
const int f = pucch->frame;
|
const int f = pucch->frame;
|
||||||
@@ -1306,32 +1274,20 @@ bool nr_acknack_scheduling(int mod_id,
|
|||||||
LOG_D(MAC,"2. DL slot %d, UL_ACK %d (index %d)\n",slot,pucch->ul_slot,i);
|
LOG_D(MAC,"2. DL slot %d, UL_ACK %d (index %d)\n",slot,pucch->ul_slot,i);
|
||||||
|
|
||||||
pucch->dai_c++;
|
pucch->dai_c++;
|
||||||
const int pucch_res = r_pucch<0 ? pucch_index_used[pucch->ul_slot] : r_pucch;
|
pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources
|
||||||
pucch->resource_indicator = pucch_res;
|
|
||||||
pucch_index_used[pucch->ul_slot] += 1;
|
|
||||||
AssertFatal(pucch_index_used[pucch->ul_slot] <= n_res,
|
|
||||||
"UE %d in %4d.%2d: pucch_index_used is %d (%d available)\n",
|
|
||||||
UE_id,
|
|
||||||
pucch->frame,
|
|
||||||
pucch->ul_slot,
|
|
||||||
pucch_index_used[pucch->ul_slot],
|
|
||||||
n_res);
|
|
||||||
|
|
||||||
/* verify that at that slot and symbol, resources are free. We only do this
|
/* verify that at that slot and symbol, resources are free. We only do this
|
||||||
* for initialCyclicShift 0 (we assume it always has that one), so other
|
* for initialCyclicShift 0 (we assume it always has that one), so other
|
||||||
* initialCyclicShifts can overlap with ICS 0!*/
|
* initialCyclicShifts can overlap with ICS 0!*/
|
||||||
if (pucch_Config) {
|
const NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||||
const NR_PUCCH_Resource_t *resource =
|
const NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[pucch->resource_indicator];
|
||||||
pucch_Config->resourceToAddModList->list.array[pucch_res];
|
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
|
||||||
DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
|
if (resource->format.choice.format0->initialCyclicShift == 0) {
|
||||||
if (resource->format.choice.format0->initialCyclicShift == 0) {
|
uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE];
|
||||||
uint16_t *vrb_map_UL = &RC.nrmac[mod_id]->common_channels[CC_id].vrb_map_UL[pucch->ul_slot * MAX_BWP_SIZE];
|
const uint16_t symb = 1 << resource->format.choice.format0->startingSymbolIndex;
|
||||||
const uint16_t symb = 1 << resource->format.choice.format0->startingSymbolIndex;
|
if ((vrb_map_UL[resource->startingPRB] & symb) != 0)
|
||||||
AssertFatal((vrb_map_UL[resource->startingPRB] & symb) == 0,
|
LOG_W(MAC, "symbol 0x%x is not free for PUCCH alloc in vrb_map_UL at RB %ld and slot %d.%d\n", symb, resource->startingPRB, pucch->frame, pucch->ul_slot);
|
||||||
"symbol %x is not free for PUCCH alloc in vrb_map_UL at RB %ld and slot %d\n",
|
vrb_map_UL[resource->startingPRB] |= symb;
|
||||||
symb, resource->startingPRB, pucch->ul_slot);
|
|
||||||
vrb_map_UL[resource->startingPRB] |= symb;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1463,3 +1419,154 @@ uint16_t compute_pucch_prb_size(uint8_t format,
|
|||||||
AssertFatal(1==0,"Not yet implemented");
|
AssertFatal(1==0,"Not yet implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nr_sr_reporting(int Mod_idP, frame_t SFN, sub_frame_t slot)
|
||||||
|
{
|
||||||
|
gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP];
|
||||||
|
if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot))
|
||||||
|
return;
|
||||||
|
NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon;
|
||||||
|
const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||||
|
NR_UE_info_t *UE_info = &nrmac->UE_info;
|
||||||
|
NR_list_t *UE_list = &UE_info->list;
|
||||||
|
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||||
|
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||||
|
NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
|
||||||
|
AssertFatal(pucch_Config->schedulingRequestResourceToAddModList->list.count>0,"NO SR configuration available");
|
||||||
|
|
||||||
|
for (int SR_resource_id =0; SR_resource_id < pucch_Config->schedulingRequestResourceToAddModList->list.count;SR_resource_id++) {
|
||||||
|
NR_SchedulingRequestResourceConfig_t *SchedulingRequestResourceConfig = pucch_Config->schedulingRequestResourceToAddModList->list.array[SR_resource_id];
|
||||||
|
|
||||||
|
int SR_period; int SR_offset;
|
||||||
|
|
||||||
|
periodicity__SRR(SchedulingRequestResourceConfig,&SR_period,&SR_offset);
|
||||||
|
// convert to int to avoid underflow of uint
|
||||||
|
int sfn_sf = SFN * n_slots_frame + slot;
|
||||||
|
if ((sfn_sf - SR_offset) % SR_period != 0)
|
||||||
|
continue;
|
||||||
|
LOG_D(MAC, "%4d.%2d Scheduling Request identified\n", SFN, slot);
|
||||||
|
NR_PUCCH_ResourceId_t *PucchResourceId = SchedulingRequestResourceConfig->resource;
|
||||||
|
|
||||||
|
int found = -1;
|
||||||
|
NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[0]; // set with formats 0,1
|
||||||
|
int n_list = pucchresset->resourceList.list.count;
|
||||||
|
for (int i=0; i<n_list; i++) {
|
||||||
|
if (*pucchresset->resourceList.list.array[i] == *PucchResourceId )
|
||||||
|
found = i;
|
||||||
|
}
|
||||||
|
AssertFatal(found>-1,"SR resource not found among PUCCH resources");
|
||||||
|
|
||||||
|
/* loop through nFAPI PUCCH messages: if the UEs is in there in this slot
|
||||||
|
* with the resource_indicator, it means we already allocated that PUCCH
|
||||||
|
* resource for AckNack (e.g., the UE has been scheduled often), and we
|
||||||
|
* just need to add the SR_flag. Otherwise, just allocate in the internal
|
||||||
|
* PUCCH resource, and nr_schedule_pucch() will handle the rest */
|
||||||
|
NR_PUCCH_Resource_t *pucch_res = pucch_Config->resourceToAddModList->list.array[found];
|
||||||
|
/* for the moment, can only handle SR on PUCCH Format 0 */
|
||||||
|
DevAssert(pucch_res->format.present == NR_PUCCH_Resource__format_PR_format0);
|
||||||
|
nfapi_nr_ul_tti_request_t *ul_tti_req = &nrmac->UL_tti_req_ahead[0][slot];
|
||||||
|
bool nfapi_allocated = false;
|
||||||
|
for (int i = 0; i < ul_tti_req->n_pdus; ++i) {
|
||||||
|
if (ul_tti_req->pdus_list[i].pdu_type != NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE)
|
||||||
|
continue;
|
||||||
|
nfapi_nr_pucch_pdu_t *pdu = &ul_tti_req->pdus_list[i].pucch_pdu;
|
||||||
|
/* check that it is our PUCCH F0. Assuming there can be only one */
|
||||||
|
if (pdu->rnti == UE_info->rnti[UE_id]
|
||||||
|
&& pdu->format_type == 0 // does not use NR_PUCCH_Resource__format_PR_format0
|
||||||
|
&& pdu->initial_cyclic_shift == pucch_res->format.choice.format0->initialCyclicShift
|
||||||
|
&& pdu->nr_of_symbols == pucch_res->format.choice.format0->nrofSymbols
|
||||||
|
&& pdu->start_symbol_index == pucch_res->format.choice.format0->startingSymbolIndex) {
|
||||||
|
LOG_D(MAC,"%4d.%2d adding SR_flag 1 to PUCCH nFAPI SR for RNTI %04x\n", SFN, slot, pdu->rnti);
|
||||||
|
pdu->sr_flag = 1;
|
||||||
|
nfapi_allocated = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nfapi_allocated) // break scheduling resource loop, continue next UE
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* we did not find it: check if current PUCCH is for the current slot, in
|
||||||
|
* which case we add the SR to it; otherwise, allocate SR separately */
|
||||||
|
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[0];
|
||||||
|
if (curr_pucch->frame == SFN && curr_pucch->ul_slot == slot) {
|
||||||
|
if (curr_pucch->resource_indicator != found) {
|
||||||
|
LOG_W(MAC, "%4d.%2d expected PUCCH in this slot to have resource indicator of SR (%d), skipping SR\n", SFN, slot, found);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
curr_pucch->sr_flag = true;
|
||||||
|
} else {
|
||||||
|
NR_sched_pucch_t sched_sr;
|
||||||
|
memset(&sched_sr, 0, sizeof(sched_sr));
|
||||||
|
sched_sr.frame = SFN;
|
||||||
|
sched_sr.ul_slot = slot;
|
||||||
|
sched_sr.resource_indicator = found;
|
||||||
|
sched_sr.sr_flag = true;
|
||||||
|
nr_fill_nfapi_pucch(Mod_idP, SFN, slot, &sched_sr, UE_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void periodicity__SRR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRec, int *period, int *offset)
|
||||||
|
{
|
||||||
|
NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR P_O = SchedulingReqRec->periodicityAndOffset->present;
|
||||||
|
switch (P_O){
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl1:
|
||||||
|
*period = 1;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl1;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl2:
|
||||||
|
*period = 2;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl2;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl4:
|
||||||
|
*period = 4;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl4;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl5:
|
||||||
|
*period = 5;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl5;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl8:
|
||||||
|
*period = 8;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl8;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10:
|
||||||
|
*period = 10;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl10;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl16:
|
||||||
|
*period = 16;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl16;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl20:
|
||||||
|
*period = 20;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl20;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl40:
|
||||||
|
*period = 40;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl40;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl80:
|
||||||
|
*period = 80;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl80;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl160:
|
||||||
|
*period = 160;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl160;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl320:
|
||||||
|
*period = 320;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl320;
|
||||||
|
break;
|
||||||
|
case NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl640:
|
||||||
|
*period = 640;
|
||||||
|
*offset = SchedulingReqRec->periodicityAndOffset->choice.sl640;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
AssertFatal(1==0,"No periodicityAndOffset resources found in schedulingrequestresourceconfig");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -789,6 +789,34 @@ long get_K2(NR_ServingCellConfigCommon_t *scc,NR_BWP_Uplink_t *ubwp, int time_do
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nr_UE_is_to_be_scheduled(module_id_t mod_id, int CC_id, int UE_id, frame_t frame, sub_frame_t slot)
|
||||||
|
{
|
||||||
|
const NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
|
||||||
|
const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160};
|
||||||
|
const int n = slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||||
|
const int now = frame * n + slot;
|
||||||
|
|
||||||
|
const struct gNB_MAC_INST_s *nrmac = RC.nrmac[mod_id];
|
||||||
|
const NR_UE_sched_ctrl_t *sched_ctrl = &nrmac->UE_info.UE_sched_ctrl[UE_id];
|
||||||
|
const int last_ul_sched = sched_ctrl->last_ul_frame * n + sched_ctrl->last_ul_slot;
|
||||||
|
|
||||||
|
const int diff = (now - last_ul_sched + 1024 * n) % (1024 * n);
|
||||||
|
/* UE is to be scheduled if
|
||||||
|
* (1) we think the UE has more bytes awaiting than what we scheduled
|
||||||
|
* (2) there is a scheduling request
|
||||||
|
* (3) or we did not schedule it in more than 10 frames */
|
||||||
|
const bool has_data = sched_ctrl->estimated_ul_buffer > sched_ctrl->sched_ul_bytes;
|
||||||
|
const bool high_inactivity = diff >= nrmac->ulsch_max_slots_inactivity;
|
||||||
|
LOG_D(MAC,
|
||||||
|
"%4d.%2d UL inactivity %d slots has_data %d SR %d\n",
|
||||||
|
frame,
|
||||||
|
slot,
|
||||||
|
diff,
|
||||||
|
has_data,
|
||||||
|
sched_ctrl->SR);
|
||||||
|
return has_data || sched_ctrl->SR || high_inactivity;
|
||||||
|
}
|
||||||
|
|
||||||
int next_list_entry_looped(NR_list_t *list, int UE_id)
|
int next_list_entry_looped(NR_list_t *list, int UE_id)
|
||||||
{
|
{
|
||||||
if (UE_id < 0)
|
if (UE_id < 0)
|
||||||
@@ -920,7 +948,6 @@ void update_ul_ue_R_Qm(NR_sched_pusch_t *sched_pusch, const NR_pusch_semi_static
|
|||||||
|
|
||||||
float ul_thr_ue[MAX_MOBILES_PER_GNB];
|
float ul_thr_ue[MAX_MOBILES_PER_GNB];
|
||||||
uint32_t ul_pf_tbs[3][28]; // pre-computed, approximate TBS values for PF coefficient
|
uint32_t ul_pf_tbs[3][28]; // pre-computed, approximate TBS values for PF coefficient
|
||||||
int bsr0ue = -1;
|
|
||||||
void pf_ul(module_id_t module_id,
|
void pf_ul(module_id_t module_id,
|
||||||
frame_t frame,
|
frame_t frame,
|
||||||
sub_frame_t slot,
|
sub_frame_t slot,
|
||||||
@@ -939,12 +966,6 @@ void pf_ul(module_id_t module_id,
|
|||||||
int ue_array[MAX_MOBILES_PER_GNB];
|
int ue_array[MAX_MOBILES_PER_GNB];
|
||||||
NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB };
|
NR_list_t UE_sched = { .head = -1, .next = ue_array, .tail = -1, .len = MAX_MOBILES_PER_GNB };
|
||||||
|
|
||||||
/* Hack: currently, we do not have SR, and need to schedule UEs continuously.
|
|
||||||
* To keep the wasted resources low, we switch UEs to be scheduled in a
|
|
||||||
* round-robin fashion below, and only schedule a UE with BSR=0 if it is the
|
|
||||||
* selected one */
|
|
||||||
bsr0ue = next_list_entry_looped(UE_list, bsr0ue);
|
|
||||||
|
|
||||||
/* Loop UE_list to calculate throughput and coeff */
|
/* Loop UE_list to calculate throughput and coeff */
|
||||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||||
|
|
||||||
@@ -979,11 +1000,16 @@ void pf_ul(module_id_t module_id,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check BSR and schedule UE if it is zero to avoid starvation, since we do
|
const int B = max(0, sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes);
|
||||||
* not have SR (yet) */
|
/* preprocessor computed sched_frame/sched_slot */
|
||||||
if (sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes <= 0) {
|
const bool do_sched = nr_UE_is_to_be_scheduled(module_id, 0, UE_id, sched_pusch->frame, sched_pusch->slot);
|
||||||
if (UE_id != bsr0ue)
|
|
||||||
continue;
|
if (B == 0 && !do_sched)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Schedule UE on SR or UL inactivity and no data (otherwise, will be scheduled
|
||||||
|
* based on data to transmit) */
|
||||||
|
if (B == 0 && do_sched) {
|
||||||
/* if no data, pre-allocate 5RB */
|
/* if no data, pre-allocate 5RB */
|
||||||
bool freeCCE = find_free_CCE(module_id, slot, UE_id);
|
bool freeCCE = find_free_CCE(module_id, slot, UE_id);
|
||||||
if (!freeCCE) {
|
if (!freeCCE) {
|
||||||
@@ -1162,7 +1188,7 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
|
|||||||
int K2 = get_K2(scc, sched_ctrl->active_ubwp, tda, mu);
|
int K2 = get_K2(scc, sched_ctrl->active_ubwp, tda, mu);
|
||||||
const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]);
|
const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]);
|
||||||
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
|
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
|
||||||
if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[slot / 64], sched_slot))
|
if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sched_ctrl->sched_pusch.slot = sched_slot;
|
sched_ctrl->sched_pusch.slot = sched_slot;
|
||||||
@@ -1281,6 +1307,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
|
|||||||
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
|
||||||
UE_info->mac_stats[UE_id].ulsch_current_bytes = 0;
|
UE_info->mac_stats[UE_id].ulsch_current_bytes = 0;
|
||||||
|
|
||||||
/* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in
|
/* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in
|
||||||
* every TTI are pre-populated by the preprocessor and used below */
|
* every TTI are pre-populated by the preprocessor and used below */
|
||||||
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
|
||||||
@@ -1289,6 +1316,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint16_t rnti = UE_info->rnti[UE_id];
|
uint16_t rnti = UE_info->rnti[UE_id];
|
||||||
|
sched_ctrl->SR = false;
|
||||||
|
|
||||||
int8_t harq_id = sched_pusch->ul_harq_pid;
|
int8_t harq_id = sched_pusch->ul_harq_pid;
|
||||||
if (harq_id < 0) {
|
if (harq_id < 0) {
|
||||||
@@ -1345,6 +1373,8 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
|
|||||||
cur_harq->ndi);
|
cur_harq->ndi);
|
||||||
}
|
}
|
||||||
UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size;
|
UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size;
|
||||||
|
sched_ctrl->last_ul_frame = sched_pusch->frame;
|
||||||
|
sched_ctrl->last_ul_slot = sched_pusch->slot;
|
||||||
|
|
||||||
LOG_D(NR_MAC,
|
LOG_D(NR_MAC,
|
||||||
"%4d.%2d RNTI %04x UL sched %4d.%2d start %2d RBS %3d startSymbol %2d nb_symbol %2d MCS %2d TBS %4d HARQ PID %2d round %d NDI %d est %6d sched %6d est BSR %6d\n",
|
"%4d.%2d RNTI %04x UL sched %4d.%2d start %2d RBS %3d startSymbol %2d nb_symbol %2d MCS %2d TBS %4d HARQ PID %2d round %d NDI %d est %6d sched %6d est BSR %6d\n",
|
||||||
|
|||||||
@@ -423,4 +423,10 @@ bool nr_find_nb_rb(uint16_t Qm,
|
|||||||
uint32_t *tbs,
|
uint32_t *tbs,
|
||||||
uint16_t *nb_rb);
|
uint16_t *nb_rb);
|
||||||
|
|
||||||
|
void nr_sr_reporting(int Mod_idP, frame_t frameP, sub_frame_t slotP);
|
||||||
|
|
||||||
|
void periodicity__SRR (NR_SchedulingRequestResourceConfig_t *SchedulingReqRecconf,
|
||||||
|
int *period,
|
||||||
|
int *offset);
|
||||||
|
|
||||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||||
|
|||||||
@@ -524,11 +524,9 @@ typedef struct {
|
|||||||
int cce_index;
|
int cce_index;
|
||||||
uint8_t aggregation_level;
|
uint8_t aggregation_level;
|
||||||
|
|
||||||
/// PUCCH scheduling information. Array of three, we assume for the moment:
|
/// PUCCH scheduling information. Array of two: HARQ+SR in the first field,
|
||||||
/// HARQ in the first field, SR in second, CSI in third (as fixed by RRC
|
/// CSI in second. This order is important for nr_acknack_scheduling()!
|
||||||
/// conf., i.e. if actually present). The order is important for
|
NR_sched_pucch_t sched_pucch[2];
|
||||||
/// nr_acknack_scheduling()!
|
|
||||||
NR_sched_pucch_t sched_pucch[3];
|
|
||||||
|
|
||||||
/// PUSCH semi-static configuration: is not cleared across TTIs
|
/// PUSCH semi-static configuration: is not cleared across TTIs
|
||||||
NR_pusch_semi_static_t pusch_semi_static;
|
NR_pusch_semi_static_t pusch_semi_static;
|
||||||
@@ -549,6 +547,9 @@ typedef struct {
|
|||||||
NR_pdsch_semi_static_t pdsch_semi_static;
|
NR_pdsch_semi_static_t pdsch_semi_static;
|
||||||
/// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI
|
/// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI
|
||||||
NR_sched_pdsch_t sched_pdsch;
|
NR_sched_pdsch_t sched_pdsch;
|
||||||
|
/// For UL synchronization: store last UL scheduling grant
|
||||||
|
frame_t last_ul_frame;
|
||||||
|
sub_frame_t last_ul_slot;
|
||||||
|
|
||||||
/// total amount of data awaiting for this UE
|
/// total amount of data awaiting for this UE
|
||||||
uint32_t num_total_bytes;
|
uint32_t num_total_bytes;
|
||||||
@@ -569,6 +570,8 @@ typedef struct {
|
|||||||
int pucch_consecutive_dtx_cnt;
|
int pucch_consecutive_dtx_cnt;
|
||||||
int ul_failure;
|
int ul_failure;
|
||||||
struct CSI_Report CSI_report[MAX_CSI_REPORTS];
|
struct CSI_Report CSI_report[MAX_CSI_REPORTS];
|
||||||
|
bool SR;
|
||||||
|
|
||||||
/// information about every HARQ process
|
/// information about every HARQ process
|
||||||
NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES];
|
NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES];
|
||||||
/// HARQ processes that are free
|
/// HARQ processes that are free
|
||||||
@@ -716,10 +719,6 @@ typedef struct gNB_MAC_INST_s {
|
|||||||
int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE];
|
int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE];
|
||||||
/// list of allocated beams per period
|
/// list of allocated beams per period
|
||||||
int16_t *tdd_beam_association;
|
int16_t *tdd_beam_association;
|
||||||
/// PUCCH: keep track of the resources has already been used by saving the
|
|
||||||
/// highest index not yet been used in a given slot. Dynamically allocated
|
|
||||||
/// so we can have it for every slot as a function of the numerology
|
|
||||||
int *pucch_index_used[MAX_NUM_BWP];
|
|
||||||
|
|
||||||
/// bitmap of DLSCH slots, can hold up to 160 slots
|
/// bitmap of DLSCH slots, can hold up to 160 slots
|
||||||
uint64_t dlsch_slot_bitmap[3];
|
uint64_t dlsch_slot_bitmap[3];
|
||||||
@@ -733,6 +732,9 @@ typedef struct gNB_MAC_INST_s {
|
|||||||
/// points to the right UL slot
|
/// points to the right UL slot
|
||||||
int *preferred_ul_tda[MAX_NUM_BWP];
|
int *preferred_ul_tda[MAX_NUM_BWP];
|
||||||
|
|
||||||
|
/// maximum number of slots before a UE will be scheduled ULSCH automatically
|
||||||
|
uint32_t ulsch_max_slots_inactivity;
|
||||||
|
|
||||||
/// DL preprocessor for differentiated scheduling
|
/// DL preprocessor for differentiated scheduling
|
||||||
nr_pp_impl_dl pre_processor_dl;
|
nr_pp_impl_dl pre_processor_dl;
|
||||||
/// UL preprocessor for differentiated scheduling
|
/// UL preprocessor for differentiated scheduling
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ void nr_rlc_bearer_init_ul_spec(struct NR_LogicalChannelConfig *mac_LogicalChann
|
|||||||
|
|
||||||
mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = calloc(1,sizeof(*mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup));
|
mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = calloc(1,sizeof(*mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup));
|
||||||
*mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = 1;
|
*mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelGroup = 1;
|
||||||
mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = NULL;
|
mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = calloc(1,sizeof(*mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID));
|
||||||
|
*mac_LogicalChannelConfig->ul_SpecificParameters->schedulingRequestID = 0;
|
||||||
mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = false;
|
mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_Mask = false;
|
||||||
mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = false;
|
mac_LogicalChannelConfig->ul_SpecificParameters->logicalChannelSR_DelayTimerApplied = false;
|
||||||
mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL;
|
mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL;
|
||||||
|
|||||||
@@ -105,14 +105,8 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
UL_info->uci_ind.num_ucis = 0;
|
UL_info->uci_ind.num_ucis = 0;
|
||||||
|
|
||||||
// mark corresponding PUCCH resources as free
|
|
||||||
// NOTE: we just assume it is BWP ID 0 and 1, to be revised for multiple BWPs
|
|
||||||
RC.nrmac[mod_id]->pucch_index_used[0][slot] = 0;
|
|
||||||
RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void handle_nr_ulsch(NR_UL_IND_t *UL_info)
|
void handle_nr_ulsch(NR_UL_IND_t *UL_info)
|
||||||
{
|
{
|
||||||
if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) {
|
if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) {
|
||||||
|
|||||||
@@ -1644,7 +1644,8 @@ uint16_t do_RRCReconfiguration(
|
|||||||
// 1,
|
// 1,
|
||||||
// 1,
|
// 1,
|
||||||
// carrier->pdsch_AntennaPorts,
|
// carrier->pdsch_AntennaPorts,
|
||||||
// carrier->initial_csi_index[gnb_rrc_inst->Nb_ue]);
|
// carrier->initial_csi_index[ue_context_p->local_uid + 1],
|
||||||
|
// ue_context_pP->local_uid);
|
||||||
|
|
||||||
/******************** Meas Config ********************/
|
/******************** Meas Config ********************/
|
||||||
// measConfig
|
// measConfig
|
||||||
|
|||||||
@@ -85,14 +85,16 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
|||||||
int scg_id,
|
int scg_id,
|
||||||
int servCellIndex,
|
int servCellIndex,
|
||||||
int n_physical_antenna_ports,
|
int n_physical_antenna_ports,
|
||||||
int initial_csi_index);
|
int initial_csi_index,
|
||||||
|
int uid);
|
||||||
|
|
||||||
void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
|
||||||
NR_ServingCellConfig_t *servingcellconfigdedicated,
|
NR_ServingCellConfig_t *servingcellconfigdedicated,
|
||||||
NR_RRCReconfiguration_IEs_t *reconfig,
|
NR_RRCReconfiguration_IEs_t *reconfig,
|
||||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||||
int n_physical_antenna_ports,
|
int n_physical_antenna_ports,
|
||||||
int initial_csi_index);
|
int initial_csi_index,
|
||||||
|
int uid);
|
||||||
|
|
||||||
void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
|
void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
|
||||||
int eps_bearer_id, int rb_id,
|
int eps_bearer_id, int rb_id,
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
|||||||
ue_context_p->ue_context.reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration;
|
ue_context_p->ue_context.reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration;
|
||||||
NR_RRCReconfiguration_IEs_t *reconfig_ies=calloc(1,sizeof(NR_RRCReconfiguration_IEs_t));
|
NR_RRCReconfiguration_IEs_t *reconfig_ies=calloc(1,sizeof(NR_RRCReconfiguration_IEs_t));
|
||||||
ue_context_p->ue_context.reconfig->criticalExtensions.choice.rrcReconfiguration = reconfig_ies;
|
ue_context_p->ue_context.reconfig->criticalExtensions.choice.rrcReconfiguration = reconfig_ies;
|
||||||
carrier->initial_csi_index[rrc->Nb_ue] = 0;
|
carrier->initial_csi_index[ue_context_p->local_uid + 1] = 0;
|
||||||
ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t));
|
ue_context_p->ue_context.rb_config = calloc(1,sizeof(NR_RRCReconfiguration_t));
|
||||||
if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1 || get_softmodem_params()->sa == 1){
|
if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1 || get_softmodem_params()->sa == 1){
|
||||||
fill_default_rbconfig(ue_context_p->ue_context.rb_config,
|
fill_default_rbconfig(ue_context_p->ue_context.rb_config,
|
||||||
@@ -245,14 +245,16 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
|
|||||||
reconfig_ies,
|
reconfig_ies,
|
||||||
ue_context_p->ue_context.secondaryCellGroup,
|
ue_context_p->ue_context.secondaryCellGroup,
|
||||||
carrier->pdsch_AntennaPorts,
|
carrier->pdsch_AntennaPorts,
|
||||||
carrier->initial_csi_index[rrc->Nb_ue]);
|
carrier->initial_csi_index[ue_context_p->local_uid + 1],
|
||||||
|
ue_context_p->local_uid);
|
||||||
} else {
|
} else {
|
||||||
fill_default_reconfig(carrier->servingcellconfigcommon,
|
fill_default_reconfig(carrier->servingcellconfigcommon,
|
||||||
NULL,
|
NULL,
|
||||||
reconfig_ies,
|
reconfig_ies,
|
||||||
ue_context_p->ue_context.secondaryCellGroup,
|
ue_context_p->ue_context.secondaryCellGroup,
|
||||||
carrier->pdsch_AntennaPorts,
|
carrier->pdsch_AntennaPorts,
|
||||||
carrier->initial_csi_index[rrc->Nb_ue]);
|
carrier->initial_csi_index[ue_context_p->local_uid + 1],
|
||||||
|
ue_context_p->local_uid);
|
||||||
}
|
}
|
||||||
ue_context_p->ue_id_rnti = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
|
ue_context_p->ue_id_rnti = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
|
||||||
NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config));
|
NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config));
|
||||||
|
|||||||
@@ -129,7 +129,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
|||||||
int scg_id,
|
int scg_id,
|
||||||
int servCellIndex,
|
int servCellIndex,
|
||||||
int n_physical_antenna_ports,
|
int n_physical_antenna_ports,
|
||||||
int initial_csi_index) {
|
int initial_csi_index,
|
||||||
|
int uid) {
|
||||||
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
|
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
|
||||||
AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
|
AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
|
||||||
|
|
||||||
@@ -172,7 +173,17 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
|||||||
|
|
||||||
secondaryCellGroup->mac_CellGroupConfig=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig));
|
secondaryCellGroup->mac_CellGroupConfig=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig));
|
||||||
secondaryCellGroup->mac_CellGroupConfig->drx_Config = NULL;
|
secondaryCellGroup->mac_CellGroupConfig->drx_Config = NULL;
|
||||||
secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig = NULL;
|
|
||||||
|
secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig = calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig));
|
||||||
|
secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList = calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList));
|
||||||
|
NR_SchedulingRequestToAddMod_t *SchedulingRequestConf = calloc(1,sizeof(*SchedulingRequestConf));
|
||||||
|
SchedulingRequestConf->schedulingRequestId = 0; //Could be changed
|
||||||
|
SchedulingRequestConf->sr_ProhibitTimer = calloc(1,sizeof(*SchedulingRequestConf->sr_ProhibitTimer));
|
||||||
|
*SchedulingRequestConf->sr_ProhibitTimer = NR_SchedulingRequestToAddMod__sr_ProhibitTimer_ms16;
|
||||||
|
SchedulingRequestConf->sr_TransMax = NR_SchedulingRequestToAddMod__sr_TransMax_n32;
|
||||||
|
ASN_SEQUENCE_ADD(&secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToAddModList->list,SchedulingRequestConf);
|
||||||
|
secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig->schedulingRequestToReleaseList = NULL;
|
||||||
|
|
||||||
secondaryCellGroup->mac_CellGroupConfig->bsr_Config=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->bsr_Config));
|
secondaryCellGroup->mac_CellGroupConfig->bsr_Config=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->bsr_Config));
|
||||||
secondaryCellGroup->mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10;
|
secondaryCellGroup->mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10;
|
||||||
secondaryCellGroup->mac_CellGroupConfig->bsr_Config->retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf160;
|
secondaryCellGroup->mac_CellGroupConfig->bsr_Config->retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf160;
|
||||||
@@ -239,7 +250,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
|||||||
if ((bitmap>>(63-i))&0x01){
|
if ((bitmap>>(63-i))&0x01){
|
||||||
ssbElem[n_ssb] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
ssbElem[n_ssb] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
|
||||||
ssbElem[n_ssb]->ssb = i;
|
ssbElem[n_ssb]->ssb = i;
|
||||||
ssbElem[n_ssb]->ra_PreambleIndex = 63;
|
ssbElem[n_ssb]->ra_PreambleIndex = 63 - (uid % 64);
|
||||||
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[n_ssb]);
|
ASN_SEQUENCE_ADD(&secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra->resources.choice.ssb->ssb_ResourceList.list,ssbElem[n_ssb]);
|
||||||
n_ssb++;
|
n_ssb++;
|
||||||
}
|
}
|
||||||
@@ -251,8 +262,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
|||||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants));
|
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants));
|
||||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->present = NR_SetupRelease_RLF_TimersAndConstants_PR_setup;
|
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->present = NR_SetupRelease_RLF_TimersAndConstants_PR_setup;
|
||||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup));
|
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup=calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup));
|
||||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->t310 = NR_RLF_TimersAndConstants__t310_ms2000;
|
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->t310 = NR_RLF_TimersAndConstants__t310_ms4000;
|
||||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->n310 = NR_RLF_TimersAndConstants__n310_n10;
|
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->n310 = NR_RLF_TimersAndConstants__n310_n20;
|
||||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->n311 = NR_RLF_TimersAndConstants__n311_n1;
|
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->n311 = NR_RLF_TimersAndConstants__n311_n1;
|
||||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1 = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1));
|
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1 = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1));
|
||||||
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1->t311 = NR_RLF_TimersAndConstants__ext1__t311_ms30000;
|
secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->ext1->t311 = NR_RLF_TimersAndConstants__ext1__t311_ms30000;
|
||||||
@@ -963,7 +974,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
|||||||
NR_PUCCH_Resource_t *pucchres2=calloc(1,sizeof(*pucchres2));
|
NR_PUCCH_Resource_t *pucchres2=calloc(1,sizeof(*pucchres2));
|
||||||
NR_PUCCH_Resource_t *pucchres3=calloc(1,sizeof(*pucchres3));
|
NR_PUCCH_Resource_t *pucchres3=calloc(1,sizeof(*pucchres3));
|
||||||
pucchres0->pucch_ResourceId=1;
|
pucchres0->pucch_ResourceId=1;
|
||||||
pucchres0->startingPRB=8;
|
pucchres0->startingPRB= (8 + uid) % curr_bwp;
|
||||||
pucchres0->intraSlotFrequencyHopping=NULL;
|
pucchres0->intraSlotFrequencyHopping=NULL;
|
||||||
pucchres0->secondHopPRB=NULL;
|
pucchres0->secondHopPRB=NULL;
|
||||||
pucchres0->format.present= NR_PUCCH_Resource__format_PR_format0;
|
pucchres0->format.present= NR_PUCCH_Resource__format_PR_format0;
|
||||||
@@ -974,7 +985,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
|||||||
ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres0);
|
ASN_SEQUENCE_ADD(&pucch_Config->resourceToAddModList->list,pucchres0);
|
||||||
|
|
||||||
pucchres1->pucch_ResourceId=2;
|
pucchres1->pucch_ResourceId=2;
|
||||||
pucchres1->startingPRB=8;
|
pucchres1->startingPRB= (8 + uid) % curr_bwp;
|
||||||
pucchres1->intraSlotFrequencyHopping=NULL;
|
pucchres1->intraSlotFrequencyHopping=NULL;
|
||||||
pucchres1->secondHopPRB=NULL;
|
pucchres1->secondHopPRB=NULL;
|
||||||
pucchres1->format.present= NR_PUCCH_Resource__format_PR_format0;
|
pucchres1->format.present= NR_PUCCH_Resource__format_PR_format0;
|
||||||
@@ -1017,7 +1028,19 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
|||||||
pucchfmt2->nrofSlots=NULL;
|
pucchfmt2->nrofSlots=NULL;
|
||||||
pucchfmt2->pi2BPSK=NULL;
|
pucchfmt2->pi2BPSK=NULL;
|
||||||
pucchfmt2->simultaneousHARQ_ACK_CSI=NULL;
|
pucchfmt2->simultaneousHARQ_ACK_CSI=NULL;
|
||||||
pucch_Config->schedulingRequestResourceToAddModList=NULL;
|
|
||||||
|
// for scheduling requestresource
|
||||||
|
pucch_Config->schedulingRequestResourceToAddModList = calloc(1,sizeof(*pucch_Config->schedulingRequestResourceToAddModList));
|
||||||
|
NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig = calloc(1,sizeof(*schedulingRequestResourceConfig));
|
||||||
|
schedulingRequestResourceConfig->schedulingRequestResourceId = 1;
|
||||||
|
schedulingRequestResourceConfig->schedulingRequestID = 0;
|
||||||
|
schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset));
|
||||||
|
schedulingRequestResourceConfig->periodicityAndOffset->present = NR_SchedulingRequestResourceConfig__periodicityAndOffset_PR_sl10;
|
||||||
|
schedulingRequestResourceConfig->periodicityAndOffset->choice.sl10 = 7;
|
||||||
|
schedulingRequestResourceConfig->resource = calloc(1,sizeof(*schedulingRequestResourceConfig->resource));
|
||||||
|
*schedulingRequestResourceConfig->resource = 1;
|
||||||
|
ASN_SEQUENCE_ADD(&pucch_Config->schedulingRequestResourceToAddModList->list,schedulingRequestResourceConfig);
|
||||||
|
|
||||||
pucch_Config->schedulingRequestResourceToReleaseList=NULL;
|
pucch_Config->schedulingRequestResourceToReleaseList=NULL;
|
||||||
pucch_Config->multi_CSI_PUCCH_ResourceList=NULL;
|
pucch_Config->multi_CSI_PUCCH_ResourceList=NULL;
|
||||||
pucch_Config->dl_DataToUL_ACK = calloc(1,sizeof(*pucch_Config->dl_DataToUL_ACK));
|
pucch_Config->dl_DataToUL_ACK = calloc(1,sizeof(*pucch_Config->dl_DataToUL_ACK));
|
||||||
@@ -1165,7 +1188,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
|
|||||||
csirep1->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic;
|
csirep1->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic;
|
||||||
csirep1->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep1->reportConfigType.choice.periodic));
|
csirep1->reportConfigType.choice.periodic = calloc(1,sizeof(*csirep1->reportConfigType.choice.periodic));
|
||||||
csirep1->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320;
|
csirep1->reportConfigType.choice.periodic->reportSlotConfig.present=NR_CSI_ReportPeriodicityAndOffset_PR_slots320;
|
||||||
csirep1->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 49;
|
csirep1->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 9 + (10 * uid) % 320;
|
||||||
NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1,sizeof(*pucchcsires1));
|
NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1,sizeof(*pucchcsires1));
|
||||||
pucchcsires1->uplinkBandwidthPartId=1;
|
pucchcsires1->uplinkBandwidthPartId=1;
|
||||||
pucchcsires1->pucch_Resource=3;
|
pucchcsires1->pucch_Resource=3;
|
||||||
@@ -1229,14 +1252,22 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
|
|||||||
NR_RRCReconfiguration_IEs_t *reconfig,
|
NR_RRCReconfiguration_IEs_t *reconfig,
|
||||||
NR_CellGroupConfig_t *secondaryCellGroup,
|
NR_CellGroupConfig_t *secondaryCellGroup,
|
||||||
int n_physical_antenna_ports,
|
int n_physical_antenna_ports,
|
||||||
int initial_csi_index) {
|
int initial_csi_index,
|
||||||
|
int uid) {
|
||||||
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
|
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
|
||||||
AssertFatal(reconfig!=NULL,"reconfig is null\n");
|
AssertFatal(reconfig!=NULL,"reconfig is null\n");
|
||||||
AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
|
AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
|
||||||
// radioBearerConfig
|
// radioBearerConfig
|
||||||
reconfig->radioBearerConfig=NULL;
|
reconfig->radioBearerConfig=NULL;
|
||||||
// secondaryCellGroup
|
// secondaryCellGroup
|
||||||
fill_default_secondaryCellGroup(servingcellconfigcommon,servingcellconfigdedicated,secondaryCellGroup,1,1,n_physical_antenna_ports,initial_csi_index);
|
fill_default_secondaryCellGroup(servingcellconfigcommon,
|
||||||
|
servingcellconfigdedicated,
|
||||||
|
secondaryCellGroup,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
n_physical_antenna_ports,
|
||||||
|
initial_csi_index,
|
||||||
|
uid);
|
||||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
|
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
|
||||||
|
|
||||||
char scg_buffer[1024];
|
char scg_buffer[1024];
|
||||||
|
|||||||
@@ -130,6 +130,18 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
|
|||||||
DevAssert(x2ap_enb_data_p != NULL);
|
DevAssert(x2ap_enb_data_p != NULL);
|
||||||
dump_trees();
|
dump_trees();
|
||||||
|
|
||||||
|
/* gNB: exit if connection to eNB failed - to be modified if needed.
|
||||||
|
* We may want to try to connect over and over again until we succeed
|
||||||
|
* but the modifications to the code to get this behavior are complex.
|
||||||
|
* Exit on error is a simple solution that can be caught by a script
|
||||||
|
* for example.
|
||||||
|
*/
|
||||||
|
if (instance_p->cell_type == CELL_MACRO_GNB
|
||||||
|
&& sctp_new_association_resp->sctp_state == SCTP_STATE_UNREACHABLE) {
|
||||||
|
X2AP_ERROR("association with eNB failed, is it running? If no, run it first. If yes, check IP addresses in your configuration file.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||||
X2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
|
X2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
|
||||||
sctp_new_association_resp->sctp_state,
|
sctp_new_association_resp->sctp_state,
|
||||||
|
|||||||
Reference in New Issue
Block a user