diff --git a/ci-scripts/auto_start_gnb.sh b/ci-scripts/auto_start_gnb.sh
new file mode 100644
index 0000000000..86ffc66d18
--- /dev/null
+++ b/ci-scripts/auto_start_gnb.sh
@@ -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
diff --git a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf
index f0c1caef7e..8fbbc8a7cd 100644
--- a/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf
+++ b/ci-scripts/conf_files/gnb.band261.tm1.32PRB.usrpn300.conf
@@ -230,6 +230,7 @@ MACRLCs = (
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
+ ulsch_max_slots_inactivity = 1;
}
);
diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
index 43e4c6b493..4afbfdcda0 100644
--- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -211,6 +211,7 @@ MACRLCs = (
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
+ ulsch_max_slots_inactivity = 1;
}
);
diff --git a/ci-scripts/datalog_rt_stats.yaml b/ci-scripts/datalog_rt_stats.yaml
new file mode 100644
index 0000000000..3680d2a19b
--- /dev/null
+++ b/ci-scripts/datalog_rt_stats.yaml
@@ -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
diff --git a/ci-scripts/html.py b/ci-scripts/html.py
index 5cdaaa0c39..de4e049adb 100644
--- a/ci-scripts/html.py
+++ b/ci-scripts/html.py
@@ -453,6 +453,37 @@ class HTMLManagement():
self.htmlFile.write(' \n')
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('
\n')
+ self.htmlFile.write(' | ---- ' + DataLog['Title'] + ' ---- | \n')
+ self.htmlFile.write('
\n')
+ self.htmlFile.write(' \n')
+ self.htmlFile.write(' | '+ DataLog['ColNames'][0] +' | \n')
+ self.htmlFile.write(' ' + DataLog['ColNames'][1] + ' | \n')
+ self.htmlFile.write(' ' + DataLog['ColNames'][2] + ' | \n')
+ self.htmlFile.write(' '+ DataLog['ColNames'][3] +' | \n')
+ self.htmlFile.write('
\n')
+
+ for k in DataLog['Data']:
+ # TestRow
+ self.htmlFile.write(' \n')
+ self.htmlFile.write(' | ' + k + ' | \n')
+ self.htmlFile.write(' ' + DataLog['Data'][k][0] + ' | \n')
+ self.htmlFile.write(' ' + DataLog['Data'][k][1] + ' | \n')
+ if float(DataLog['Data'][k][2])> DataLog['Threshold'][k]:
+ self.htmlFile.write(' ' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + ' | \n')
+ else:
+ self.htmlFile.write(' ' + DataLog['Data'][k][2] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + ' | \n')
+ self.htmlFile.write('
\n')
+ self.htmlFile.close()
+
+
def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue):
if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
self.htmlFile = open('test_results.html', 'a')
diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py
index f1f79a2435..f5f53c20b7 100644
--- a/ci-scripts/ran.py
+++ b/ci-scripts/ran.py
@@ -37,6 +37,8 @@ import logging
import os
import time
from multiprocessing import Process, Lock, SimpleQueue
+import yaml
+
#-----------------------------------------------------------
# OAI Testing modules
@@ -90,6 +92,7 @@ class RANManagement():
self.testCase_id = ''
self.epcPcapFile = ''
self.runtime_stats= ''
+ self.datalog_rt_stats={}
@@ -633,6 +636,8 @@ class RANManagement():
HTML.CreateHtmlTestRow(self.runtime_stats, 'OK', CONST.ALL_PROCESSES_OK)
else:
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.eNBstatuses[int(self.eNB_instance)] = -1
@@ -699,6 +704,21 @@ class RANManagement():
#count "problem receiving samples" msg
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():
# Runtime statistics
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
#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
- 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:
result = re.search(k, line)
if result is not None:
#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())
- #real time statistics
- #same method as above
- 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:
+ #real time statistics for gNB
+ for k in rt_keys:
result = re.search(k, line)
if result is not None:
#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
real_time_stats[k]=tmp.group(1)
+
#count "problem receiving samples" msg
result = re.search('\[PHY\]\s+problem receiving samples', str(line))
if result is not None:
@@ -920,13 +940,23 @@ class RANManagement():
logging.debug(dlsch_ulsch_stats[key])
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
- statMsg=''
- for key in real_time_stats: #for each dictionary key
- statMsg += real_time_stats[key] + '\n'
- logging.debug(real_time_stats[key])
- htmleNBFailureMsg += statMsg
+ for k in real_time_stats:
+ tmp=re.match(r'^(?P.*):\s+(?P\d+\.\d+) us;\s+\d+;\s+(?P\d+\.\d+) us;',real_time_stats[k])
+ if tmp is not None:
+ metric=tmp.group('metric')
+ 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:
statMsg = 'No real time stats found in the log file\n'
logging.debug('No real time stats found in the log file')
diff --git a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml
index 00610d430e..9e798afdc4 100644
--- a/ci-scripts/xml_files/gnb_phytest_usrp_run.xml
+++ b/ci-scripts/xml_files/gnb_phytest_usrp_run.xml
@@ -24,7 +24,7 @@
gNB-PHY-Test
Run-gNB-PHY-Test
tasks
- 2
+ 3
090101 000001 090109
@@ -40,7 +40,7 @@
IdleSleep
Sleep
- 180
+ 300
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index 6a97026d9f..51448a747f 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -553,7 +553,7 @@ void *UE_thread(void *arg) {
if (UE->is_synchronized) {
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
- 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);
start_rx_stream=0;
@@ -693,9 +693,9 @@ void *UE_thread(void *arg) {
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",
- decoded_frame_rx, curMsg->proc.frame_rx );
+ decoded_frame_rx, curMsg->proc.frame_rx);
// use previous timing_advance value to compute writeTimestamp
writeTimestamp = timestamp+
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
index bfef89ea85..df35f14869 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
@@ -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<symbol_offset/(7*(1<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->init_sync_frame += 1;
+ }
else
ue->rx_offset = ue->ssb_offset - sync_pos_frame;
-
- ue->init_sync_frame = is;
}
/*
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
index c8ee94f510..f0e6e9984b 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
@@ -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));
}
- 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)
ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot;
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index a1a65a5980..6a03d0d905 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -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);
- 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,
ue->pbch_vars[gNB_id],
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 2c2ec30951..3380429803 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -742,13 +742,7 @@ int main(int argc, char **argv)
prepare_scd(scd);
- fill_default_secondaryCellGroup(scc,
- scd,
- secondaryCellGroup,
- 0,
- 1,
- n_tx,
- 0);
+ fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0);
/* RRC parameter validation for secondaryCellGroup */
fix_scd(scd);
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index d6229f75e8..55e1ed08f3 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -686,13 +686,7 @@ int main(int argc, char **argv)
prepare_scd(scd);
- fill_default_secondaryCellGroup(scc,
- scd,
- secondaryCellGroup,
- 0,
- 1,
- n_tx,
- 0);
+ fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0);
// xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h
index dd971801e9..0dcb4829f4 100644
--- a/openair2/GNB_APP/MACRLC_nr_paramdef.h
+++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h
@@ -55,6 +55,7 @@
#define CONFIG_STRING_MACRLC_REMOTE_S_PORTC "remote_s_portc"
#define CONFIG_STRING_MACRLC_LOCAL_S_PORTD "local_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_PUCCHTARGETSNRX10 "pucch_TargetSNRx10"
#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_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_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_PUCCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:150, 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_LOCAL_S_PORTD_IDX 15
#define MACRLC_REMOTE_S_PORTD_IDX 16
+#define MACRLC_ULSCH_MAX_SLOTS_INACTIVITY 17
#define MACRLC_PUSCHTARGETSNRX10_IDX 17
#define MACRLC_PUCCHTARGETSNRX10_IDX 18
#define MACRLC_PUCCHFAILURETHRES_IDX 19
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 8eb9670934..a589797f9b 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -723,6 +723,7 @@ void RCconfig_nr_macrlc() {
}else { // other midhaul
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 0
printf("No %s configuration found \n", CONFIG_STRING_MACRLC_LIST);
diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index 85a756d90c..e5a472acae 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -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,
"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");
config_common(Mod_idP,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index 462fd7f622..289b80cc9d 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -402,7 +402,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
}
// This schedule SR
- // TODO
+ nr_sr_reporting(module_idP, frame, slot);
// Schedule CSI measurement reporting: check in slot 0 for the whole frame
if (slot == 0)
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
index f61a28e3a7..bfa46d5368 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
@@ -252,8 +252,8 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
case 3:
// long bitmap FR2 max 64 SSBs
num_ssb = 0;
- for (int i_ssb=0; i_ssb<63; i_ssb++) {
- if ((longBitmap->buf[i_ssb/8]>>(7-i_ssb))&0x01) {
+ for (int i_ssb=0; i_ssb<64; i_ssb++) {
+ if ((longBitmap->buf[i_ssb/8]>>(7-(i_ssb%8)))&0x01) {
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 ((ssb_start_symbol/14) == rel_slot){
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
index 907a7491e9..f5270a2bab 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -120,8 +120,13 @@ int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = {
void nr_schedule_pucch(int Mod_idP,
frame_t frameP,
- sub_frame_t slotP) {
- NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
+ sub_frame_t slotP)
+{
+ 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;
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
// 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
&& !curr_pucch->sr_flag
&& 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]);
curr_pucch->frame = frame;
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_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)) {
// iterate over received harq bits
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);
}
}
+
+ // 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,
@@ -1113,10 +1123,7 @@ bool nr_acknack_scheduling(int mod_id,
* * 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
* later)
- * * that the PUCCH resource set 0 (for up to 2 bits) points to the first N
- * 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! */
+ * * each UE has dedicated PUCCH Format 0 resources, and we use index 0! */
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];
pucch->r_pucch=r_pucch;
@@ -1125,12 +1132,8 @@ bool nr_acknack_scheduling(int mod_id,
__func__,
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 (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
* the same slot again */
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->ul_slot = (s + 1) % n_slots_frame;
// 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
csi_pucch->r_pucch=-1;
if (csi_pucch->csi_bits > 0
@@ -1153,6 +1156,7 @@ bool nr_acknack_scheduling(int mod_id,
pucch->ul_slot,
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->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];
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
- * ACKNACK */
- if (pucch->sr_flag + pucch->dai_c > 0) {
+ /* there is a HARQ. Check whether we can use it for this ACKNACK */
+ if (pucch->dai_c > 0) {
/* this UE already has a PUCCH occasion */
DevAssert(pucch->frame == frame);
@@ -1205,34 +1208,14 @@ bool nr_acknack_scheduling(int mod_id,
/* 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),
* 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
* wrapped around to next frame */
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,
"frame wrap around not handled in %s() yet\n",
__func__);
@@ -1240,27 +1223,11 @@ bool nr_acknack_scheduling(int mod_id,
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
pucch->ul_slot = max(pucch->ul_slot, slot + pdsch_to_harq_feedback[0]);
// 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
if (csi_pucch->csi_bits > 0
&& csi_pucch->frame == pucch->frame
@@ -1272,6 +1239,7 @@ bool nr_acknack_scheduling(int mod_id,
pucch->ul_slot,
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
* the same slot again */
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);
pucch->dai_c++;
- const int pucch_res = r_pucch<0 ? pucch_index_used[pucch->ul_slot] : r_pucch;
- 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);
+ pucch->resource_indicator = 0; // each UE has dedicated PUCCH resources
/* 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
* initialCyclicShifts can overlap with ICS 0!*/
- if (pucch_Config) {
- const NR_PUCCH_Resource_t *resource =
- pucch_Config->resourceToAddModList->list.array[pucch_res];
- DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
- 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];
- const uint16_t symb = 1 << resource->format.choice.format0->startingSymbolIndex;
- AssertFatal((vrb_map_UL[resource->startingPRB] & symb) == 0,
- "symbol %x is not free for PUCCH alloc in vrb_map_UL at RB %ld and slot %d\n",
- symb, resource->startingPRB, pucch->ul_slot);
- vrb_map_UL[resource->startingPRB] |= symb;
- }
+ const NR_PUCCH_Config_t *pucch_Config = sched_ctrl->active_ubwp->bwp_Dedicated->pucch_Config->choice.setup;
+ const NR_PUCCH_Resource_t *resource = pucch_Config->resourceToAddModList->list.array[pucch->resource_indicator];
+ DevAssert(resource->format.present == NR_PUCCH_Resource__format_PR_format0);
+ 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];
+ const uint16_t symb = 1 << resource->format.choice.format0->startingSymbolIndex;
+ if ((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);
+ vrb_map_UL[resource->startingPRB] |= symb;
}
return true;
}
@@ -1463,3 +1419,154 @@ uint16_t compute_pucch_prb_size(uint8_t format,
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; iresourceList.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");
+ }
+}
+
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 92b1c4ed99..5e5641ae14 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -789,6 +789,34 @@ long get_K2(NR_ServingCellConfigCommon_t *scc,NR_BWP_Uplink_t *ubwp, int time_do
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)
{
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];
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,
frame_t frame,
sub_frame_t slot,
@@ -939,12 +966,6 @@ void pf_ul(module_id_t module_id,
int ue_array[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 */
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;
}
- /* Check BSR and schedule UE if it is zero to avoid starvation, since we do
- * not have SR (yet) */
- if (sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes <= 0) {
- if (UE_id != bsr0ue)
- continue;
+ const int B = max(0, sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes);
+ /* preprocessor computed sched_frame/sched_slot */
+ const bool do_sched = nr_UE_is_to_be_scheduled(module_id, 0, UE_id, sched_pusch->frame, sched_pusch->slot);
+
+ 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 */
bool freeCCE = find_free_CCE(module_id, slot, UE_id);
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);
const int sched_frame = frame + (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;
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]) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
UE_info->mac_stats[UE_id].ulsch_current_bytes = 0;
+
/* dynamic PUSCH values (RB alloc, MCS, hence R, Qm, TBS) that change in
* every TTI are pre-populated by the preprocessor and used below */
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;
uint16_t rnti = UE_info->rnti[UE_id];
+ sched_ctrl->SR = false;
int8_t harq_id = sched_pusch->ul_harq_pid;
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);
}
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,
"%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",
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 502e857ee7..c23af53eed 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -423,4 +423,10 @@ bool nr_find_nb_rb(uint16_t Qm,
uint32_t *tbs,
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__*/
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index f22304aa85..88f8952dab 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -524,11 +524,9 @@ typedef struct {
int cce_index;
uint8_t aggregation_level;
- /// PUCCH scheduling information. Array of three, we assume for the moment:
- /// HARQ in the first field, SR in second, CSI in third (as fixed by RRC
- /// conf., i.e. if actually present). The order is important for
- /// nr_acknack_scheduling()!
- NR_sched_pucch_t sched_pucch[3];
+ /// PUCCH scheduling information. Array of two: HARQ+SR in the first field,
+ /// CSI in second. This order is important for nr_acknack_scheduling()!
+ NR_sched_pucch_t sched_pucch[2];
/// PUSCH semi-static configuration: is not cleared across TTIs
NR_pusch_semi_static_t pusch_semi_static;
@@ -549,6 +547,9 @@ typedef struct {
NR_pdsch_semi_static_t pdsch_semi_static;
/// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI
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
uint32_t num_total_bytes;
@@ -569,6 +570,8 @@ typedef struct {
int pucch_consecutive_dtx_cnt;
int ul_failure;
struct CSI_Report CSI_report[MAX_CSI_REPORTS];
+ bool SR;
+
/// information about every HARQ process
NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES];
/// 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];
/// list of allocated beams per period
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
uint64_t dlsch_slot_bitmap[3];
@@ -733,6 +732,9 @@ typedef struct gNB_MAC_INST_s {
/// points to the right UL slot
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
nr_pp_impl_dl pre_processor_dl;
/// UL preprocessor for differentiated scheduling
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
index 105a2b2538..464d010104 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
@@ -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 = 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_DelayTimerApplied = false;
mac_LogicalChannelConfig->ul_SpecificParameters->bitRateQueryProhibitTimer = NULL;
diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
index 321e1d638f..fa76fd00bc 100644
--- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
+++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
@@ -105,14 +105,8 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
}
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)
{
if (UL_info->rx_ind.number_of_pdus > 0 && UL_info->crc_ind.number_crcs > 0) {
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c
index 921322fbdf..9dfb20765a 100755
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c
@@ -1644,7 +1644,8 @@ uint16_t do_RRCReconfiguration(
// 1,
// 1,
// 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 ********************/
// measConfig
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 72165e97c9..feb2321cd4 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -85,14 +85,16 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
int scg_id,
int servCellIndex,
int n_physical_antenna_ports,
- int initial_csi_index);
+ int initial_csi_index,
+ int uid);
void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon,
NR_ServingCellConfig_t *servingcellconfigdedicated,
NR_RRCReconfiguration_IEs_t *reconfig,
NR_CellGroupConfig_t *secondaryCellGroup,
int n_physical_antenna_ports,
- int initial_csi_index);
+ int initial_csi_index,
+ int uid);
void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig,
int eps_bearer_id, int rb_id,
diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c
index ae9fcff378..c7be5f30f3 100644
--- a/openair2/RRC/NR/rrc_gNB_nsa.c
+++ b/openair2/RRC/NR/rrc_gNB_nsa.c
@@ -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;
NR_RRCReconfiguration_IEs_t *reconfig_ies=calloc(1,sizeof(NR_RRCReconfiguration_IEs_t));
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));
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,
@@ -245,14 +245,16 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
reconfig_ies,
ue_context_p->ue_context.secondaryCellGroup,
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 {
fill_default_reconfig(carrier->servingcellconfigcommon,
NULL,
reconfig_ies,
ue_context_p->ue_context.secondaryCellGroup,
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;
NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config));
diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c
index 290ca09d64..31f8a4ef33 100644
--- a/openair2/RRC/NR/rrc_gNB_reconfig.c
+++ b/openair2/RRC/NR/rrc_gNB_reconfig.c
@@ -129,7 +129,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
int scg_id,
int servCellIndex,
int n_physical_antenna_ports,
- int initial_csi_index) {
+ int initial_csi_index,
+ int uid) {
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon 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->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->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10;
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){
ssbElem[n_ssb] = calloc(1,sizeof(struct NR_CFRA_SSB_Resource));
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]);
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->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->t310 = NR_RLF_TimersAndConstants__t310_ms2000;
- secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->n310 = NR_RLF_TimersAndConstants__n310_n10;
+ secondaryCellGroup->spCellConfig->rlf_TimersAndConstants->choice.setup->t310 = NR_RLF_TimersAndConstants__t310_ms4000;
+ 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->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;
@@ -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 *pucchres3=calloc(1,sizeof(*pucchres3));
pucchres0->pucch_ResourceId=1;
- pucchres0->startingPRB=8;
+ pucchres0->startingPRB= (8 + uid) % curr_bwp;
pucchres0->intraSlotFrequencyHopping=NULL;
pucchres0->secondHopPRB=NULL;
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);
pucchres1->pucch_ResourceId=2;
- pucchres1->startingPRB=8;
+ pucchres1->startingPRB= (8 + uid) % curr_bwp;
pucchres1->intraSlotFrequencyHopping=NULL;
pucchres1->secondHopPRB=NULL;
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->pi2BPSK=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->multi_CSI_PUCCH_ResourceList=NULL;
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.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.choice.slots320 = 49;
+ csirep1->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320 = 9 + (10 * uid) % 320;
NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1,sizeof(*pucchcsires1));
pucchcsires1->uplinkBandwidthPartId=1;
pucchcsires1->pucch_Resource=3;
@@ -1229,14 +1252,22 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
NR_RRCReconfiguration_IEs_t *reconfig,
NR_CellGroupConfig_t *secondaryCellGroup,
int n_physical_antenna_ports,
- int initial_csi_index) {
+ int initial_csi_index,
+ int uid) {
AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
AssertFatal(reconfig!=NULL,"reconfig is null\n");
AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
// radioBearerConfig
reconfig->radioBearerConfig=NULL;
// 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);
char scg_buffer[1024];
diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c
index 321190015d..0474d417df 100644
--- a/openair2/X2AP/x2ap_eNB.c
+++ b/openair2/X2AP/x2ap_eNB.c
@@ -130,6 +130,18 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
DevAssert(x2ap_enb_data_p != NULL);
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) {
X2AP_WARN("Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n",
sctp_new_association_resp->sctp_state,