Commit cf1822be authored by Remi Hardy's avatar Remi Hardy

Integration 2021 wk18 a

MR !1145 NR_FR2_initsync_fixes
-bug fixes that caused failure in PBCH detection after initial sync in FR2

MR !1100 NR_scheduling_request
-per-UE PUCCH F0 resource, CSI, Preamble 
-Scheduling Request 
-MAC scheduler fixes

MR !1150  rh_ci_phy_test_improve
-beautified HTML report for 5G NR phy test

MR !1113 hack-exit-gnb-when-no-enb-nsa
-Exit gNB 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
parents 158c0639 c2acb9e9
#!/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;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
ulsch_max_slots_inactivity = 1;
}
);
......
......@@ -211,6 +211,7 @@ MACRLCs = (
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
ulsch_max_slots_inactivity = 1;
}
);
......
#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.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):
if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)):
self.htmlFile = open('test_results.html', 'a')
......
......@@ -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<metric>.*):\s+(?P<avg>\d+\.\d+) us;\s+\d+;\s+(?P<max>\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')
......
......@@ -24,7 +24,7 @@
<htmlTabRef>gNB-PHY-Test</htmlTabRef>
<htmlTabName>Run-gNB-PHY-Test</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<repeatCount>2</repeatCount>
<repeatCount>3</repeatCount>
<TestCaseRequestedList>
090101 000001 090109
</TestCaseRequestedList>
......@@ -40,7 +40,7 @@
<testCase id="000001">
<class>IdleSleep</class>
<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>
......
......@@ -552,7 +552,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;
......@@ -692,9 +692,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+
......
......@@ -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)
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);
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;
}
/*
......
......@@ -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;
......
......@@ -142,7 +142,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind,
case FAPI_NR_RX_PDU_TYPE_MIB:
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.pdu = ue->pbch_vars[gNB_id]->decoded_output;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.additional_bits = ue->pbch_vars[gNB_id]->xtra_byte;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_index = frame_parms->ssb_index;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_index = (frame_parms->ssb_index)&0x7;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.ssb_length = frame_parms->Lmax;
rx_ind->rx_indication_body[n_pdus - 1].mib_pdu.cell_id = frame_parms->Nid_cell;
break;
......@@ -350,7 +350,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],
......
......@@ -733,13 +733,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);
......
......@@ -676,13 +676,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);
......
......@@ -55,7 +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"
/*-------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* MacRLC configuration parameters */
......@@ -79,6 +79,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}, \
}
#define MACRLC_CC_IDX 0
#define MACRLC_TRANSPORT_N_PREFERENCE_IDX 1
......@@ -97,5 +98,6 @@
#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
/*---------------------------------------------------------------------------------------------------------------------------------------------------------*/
#endif
......@@ -53,7 +53,7 @@
//#include "L1_paramdef.h"
#include "L1_nr_paramdef.h"
#include "MACRLC_paramdef.h"
#include "MACRLC_nr_paramdef.h"
#include "common/config/config_userapi.h"
//#include "RRC_config_tools.h"
#include "gnb_paramdef.h"
......@@ -698,6 +698,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<RC.nb_nr_macrlc_inst;j++)
}else {// MacRLC_ParamList.numelt > 0
AssertFatal (0,"No " CONFIG_STRING_MACRLC_LIST " configuration found");
......
......@@ -372,14 +372,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(MAC,"Configuring common parameters from NR ServingCellConfig\n");
config_common(Mod_idP,
......
......@@ -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)
......
......@@ -253,8 +253,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){
......
......@@ -745,6 +745,34 @@ long get_K2(const NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) {
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)
......@@ -874,7 +902,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,
......@@ -894,12 +921,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]) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
......@@ -931,11 +952,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)
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) {
......@@ -1106,7 +1132,7 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
int K2 = get_K2(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;
......@@ -1218,6 +1244,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;
......@@ -1225,6 +1252,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) {
......@@ -1281,6 +1309,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(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",
......
......@@ -414,4 +414,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__*/
......@@ -522,11 +522,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;
......@@ -547,6 +545,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;
......@@ -563,6 +564,8 @@ typedef struct {
int pucch_snrx10;
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
......@@ -705,10 +708,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];
......@@ -722,6 +721,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
......
......@@ -73,7 +73,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;
......
......@@ -105,10 +105,6 @@ 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 1, to be revised for multiple BWPs
RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0;
}
......
......@@ -1287,7 +1287,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
......
......@@ -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,
......
......@@ -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));
......
......@@ -149,7 +149,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");
......@@ -184,7 +185,17 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
ASN_SEQUENCE_ADD(&secondaryCellGroup->rlc_BearerToAddModList->list, RLC_BearerConfig);
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;
......@@ -251,7 +262,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++;
}
......@@ -263,8 +274,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;
......@@ -975,7 +986,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;
......@@ -986,7 +997,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;
......@@ -1029,7 +1040,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));
......@@ -1177,7 +1200,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;
......@@ -1241,14 +1264,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];
......
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment