Merge branch 'integration_2024_w06' into 'develop'
Integration: 2024.w06 Closes #733 and #732 See merge request oai/openairinterface5g!2564 * !2490 reworking configuration of LogicalChannelConfig at MAC UE * !2548 NR UE MSG3 buffer * !2556 Support RC SM aperiodic subscription for "UE RRC State Change" * !2557 fix duplicate call of RCconfig_NR_L1 * !2550 use pointer to structure instead of module_id inside MAC * address #733 * !2560 chore(ci): force rebuild of ran-base for integration branches * !2495 Sidelink configuration passed from RRC->MAC * !2220 L1 tx thread * !2559 FH 7.2 improvements * !2566 Provide right E1 instance when creating E2 agent in CU-UP * !2513 Update NR SA tutorials
This commit is contained in:
@@ -1384,9 +1384,11 @@ set (MAC_NR_SRC_UE
|
||||
${NR_UE_PHY_INTERFACE_DIR}/NR_IF_Module.c
|
||||
${NR_UE_PHY_INTERFACE_DIR}/NR_Packet_Drop.c
|
||||
${NR_UE_MAC_DIR}/config_ue.c
|
||||
${NR_UE_MAC_DIR}/config_ue_sl.c
|
||||
${NR_UE_MAC_DIR}/mac_vars.c
|
||||
${NR_UE_MAC_DIR}/main_ue_nr.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_procedures.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_procedures_sl.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_scheduler.c
|
||||
${NR_UE_MAC_DIR}/nr_ue_dci_configuration.c
|
||||
${NR_UE_MAC_DIR}/nr_ra_procedures.c
|
||||
|
||||
@@ -274,6 +274,11 @@ class Cluster:
|
||||
if result is not None:
|
||||
forceBaseImageBuild = True
|
||||
baseTag = 'ci-temp'
|
||||
# if the branch name contains integration_20xx_wyy, let rebuild ran-base
|
||||
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.ranBranch)
|
||||
if not forceBaseImageBuild and result is not None:
|
||||
forceBaseImageBuild = True
|
||||
baseTag = 'ci-temp'
|
||||
else:
|
||||
imageTag = f'develop-{self.ranCommitID[0:8]}'
|
||||
forceBaseImageBuild = True
|
||||
|
||||
@@ -419,6 +419,11 @@ class Containerize():
|
||||
if result is not None:
|
||||
forceBaseImageBuild = True
|
||||
baseTag = 'ci-temp'
|
||||
# if the branch name contains integration_20xx_wyy, let rebuild ran-base
|
||||
result = re.search('integration_20([0-9]{2})_w([0-9]{2})', self.ranBranch)
|
||||
if not forceBaseImageBuild and result is not None:
|
||||
forceBaseImageBuild = True
|
||||
baseTag = 'ci-temp'
|
||||
else:
|
||||
forceBaseImageBuild = True
|
||||
|
||||
|
||||
@@ -437,13 +437,19 @@ class HTMLManagement():
|
||||
|
||||
for k in DataLog['Data']:
|
||||
# TestRow
|
||||
avg = DataLog['Data'][k][0]
|
||||
maxval = DataLog['Data'][k][1]
|
||||
count = DataLog['Data'][k][2]
|
||||
valnorm = float(DataLog['Data'][k][3])
|
||||
dev = DataLog['DeviationThreshold'][k]
|
||||
ref = DataLog['Ref'][k]
|
||||
self.htmlFile.write(' <tr>\n')
|
||||
self.htmlFile.write(' <td colspan="3" bgcolor = "lightcyan" >' + k + ' </td>\n')
|
||||
self.htmlFile.write(' <td colspan="2" bgcolor = "lightcyan" >' + DataLog['Data'][k][0] + '; ' + DataLog['Data'][k][1] + '; ' + DataLog['Data'][k][2] + ' </td>\n')
|
||||
if float(DataLog['Data'][k][3])> DataLog['Threshold'][k]:
|
||||
self.htmlFile.write(' <th bgcolor = "red" >' + DataLog['Data'][k][3] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '</th>\n')
|
||||
self.htmlFile.write(f' <td colspan="2" bgcolor = "lightcyan" >{avg}; {maxval}; {count}</td>\n')
|
||||
if valnorm > 1.0 + dev or valnorm < 1.0 - dev:
|
||||
self.htmlFile.write(f' <th bgcolor = "red" >{valnorm} (Avg over Ref = {avg} over {ref}; max allowed deviation = {dev})</th>\n')
|
||||
else:
|
||||
self.htmlFile.write(' <th bgcolor = "green" ><font color="white">' + DataLog['Data'][k][3] + ' (Ref = ' + str(DataLog['Ref'][k]) + ' ; Thres = ' +str(DataLog['Threshold'][k])+') ' + '</th>\n')
|
||||
self.htmlFile.write(f' <th bgcolor = "green" ><font color="white">{valnorm} (Avg over Ref = {avg} over {ref}; max allowed deviation = {dev})</font></th>\n')
|
||||
self.htmlFile.write(' </tr>\n')
|
||||
self.htmlFile.close()
|
||||
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
|
||||
cell_type = "CELL_MACRO_GNB";
|
||||
|
||||
gNB_name = "gNB-Eurecom-5GNRBox";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
|
||||
plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});
|
||||
|
||||
tr_s_preference = "local_mac"
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
pdsch_AntennaPorts_XP = 2;
|
||||
pusch_AntennaPorts = 2;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
|
||||
absoluteFrequencySSB = 621312;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3600 MHz
|
||||
dl_absoluteFrequencyPointA = 620040;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 273;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=41,L=24 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 31624;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 273;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 31624;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -118;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 1,
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// MME parameters:
|
||||
mme_ip_address = ( { ipv4 = "192.168.12.26";
|
||||
ipv6 = "192:168:30::17";
|
||||
port = 36412 ;
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
NETWORK_INTERFACES : {
|
||||
GNB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24";
|
||||
GNB_INTERFACE_NAME_FOR_S1U = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = ({
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
});
|
||||
|
||||
L1s = ({
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
});
|
||||
|
||||
RUs = ({
|
||||
local_rf = "yes"
|
||||
nb_tx = 2
|
||||
nb_rx = 2
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 50;
|
||||
eNB_instances = [0];
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2";
|
||||
});
|
||||
|
||||
THREAD_STRUCT = ({
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
});
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config : {
|
||||
global_log_level = "info";
|
||||
hw_log_level = "info";
|
||||
phy_log_level = "info";
|
||||
mac_log_level = "info";
|
||||
rlc_log_level = "info";
|
||||
pdcp_log_level = "info";
|
||||
rrc_log_level = "info";
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
#this is a configuration file
|
||||
#used to build real time processing statistics
|
||||
#for 5G NR phy test (gNB terminate)
|
||||
Title : Processing Time (us) from datalog_rt_stats.100.2x2.yaml
|
||||
ColNames :
|
||||
- Metric
|
||||
- Average; Max; Count
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)
|
||||
Ref :
|
||||
feprx : 150.0
|
||||
feptx_prec : 0.0
|
||||
feptx_ofdm : 65.0
|
||||
feptx_total : 177.0
|
||||
L1 Tx processing : 700.0
|
||||
DLSCH encoding : 179.0
|
||||
L1 Rx processing : 526.0
|
||||
PUSCH inner-receiver : 400.0
|
||||
Schedule Response : 3.0
|
||||
DL & UL scheduling timing : 15.0
|
||||
UL Indication : 3.0
|
||||
Slot Indication : 17.0
|
||||
DeviationThreshold :
|
||||
feprx : 0.25
|
||||
feptx_prec : 0.25
|
||||
feptx_ofdm : 0.25
|
||||
feptx_total : 0.25
|
||||
L1 Tx processing : 0.25
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.25
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.50
|
||||
@@ -1,11 +1,11 @@
|
||||
#this is a configuration file
|
||||
#used to build real time processing statistics
|
||||
#for 5G NR phy test (gNB terminate)
|
||||
Title : Processing Time (us)
|
||||
Title : Processing Time (us) from datalog_rt_stats.1x1.60.yaml
|
||||
ColNames :
|
||||
- Metric
|
||||
- Average; Max; Count
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Threshold)
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)
|
||||
Ref :
|
||||
feprx : 46.0
|
||||
feptx_prec : 15.0
|
||||
@@ -15,20 +15,20 @@ Ref :
|
||||
DLSCH encoding : 137.0
|
||||
L1 Rx processing : 345.0
|
||||
PUSCH inner-receiver : 210.0
|
||||
PUSCH decoding : 2200.0
|
||||
Schedule Response : 48.0
|
||||
DL & UL scheduling timing : 13.0
|
||||
UL Indication : 60.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
|
||||
Schedule Response : 1.25
|
||||
DL & UL scheduling timing : 1.25
|
||||
UL Indication : 1.25
|
||||
Schedule Response : 3.0
|
||||
DL & UL scheduling timing : 8.0
|
||||
UL Indication : 3.0
|
||||
Slot Indication : 8.0
|
||||
DeviationThreshold :
|
||||
feprx : 0.25
|
||||
feptx_prec : 0.25
|
||||
feptx_ofdm : 0.25
|
||||
feptx_total : 0.25
|
||||
L1 Tx processing : 0.25
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.50
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.50
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#this is a configuration file
|
||||
#used to build real time processing statistics
|
||||
#for 5G NR phy test (gNB terminate)
|
||||
Title : Processing Time (us)
|
||||
Title : Processing Time (us) from datalog_rt_stats.2x2.yaml
|
||||
ColNames :
|
||||
- Metric
|
||||
- Average; Max; Count
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Threshold)
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)
|
||||
Ref :
|
||||
feprx : 120.0
|
||||
feptx_prec : 30.0
|
||||
@@ -15,18 +15,20 @@ Ref :
|
||||
DLSCH encoding : 230.0
|
||||
L1 Rx processing : 175.0
|
||||
PUSCH inner-receiver : 100.0
|
||||
PUSCH decoding : 180.0
|
||||
DL & UL scheduling timing : 37.0
|
||||
UL Indication : 38.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 : 1.25
|
||||
UL Indication : 1.25
|
||||
Schedule Response : 3.0
|
||||
DL & UL scheduling timing : 11.0
|
||||
UL Indication : 3.0
|
||||
Slot Indication : 14.0
|
||||
DeviationThreshold :
|
||||
feprx : 0.25
|
||||
feptx_prec : 0.25
|
||||
feptx_ofdm : 0.25
|
||||
feptx_total : 0.25
|
||||
L1 Tx processing : 0.25
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.50
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.25
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#this is a configuration file
|
||||
#used to build real time processing statistics
|
||||
#for 5G NR phy test (gNB terminate)
|
||||
Title : Processing Time (us)
|
||||
Title : Processing Time (us) from datalog_rt_stats.60.2x2.yaml
|
||||
ColNames :
|
||||
- Metric
|
||||
- Average; Max; Count
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Threshold)
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)
|
||||
Ref :
|
||||
feprx : 84.0
|
||||
feptx_prec : 14.0
|
||||
@@ -15,20 +15,20 @@ Ref :
|
||||
DLSCH encoding : 177.0
|
||||
L1 Rx processing : 345.0
|
||||
PUSCH inner-receiver : 210.0
|
||||
PUSCH decoding : 2200.0
|
||||
Schedule Response : 111.0
|
||||
DL & UL scheduling timing : 20.0
|
||||
UL Indication : 127.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
|
||||
Schedule Response : 48.0
|
||||
DL & UL scheduling timing : 1.25
|
||||
UL Indication : 1.25
|
||||
Schedule Response : 3.0
|
||||
DL & UL scheduling timing : 13.0
|
||||
UL Indication : 3.0
|
||||
Slot Indication : 15.0
|
||||
DeviationThreshold :
|
||||
feprx : 0.25
|
||||
feptx_prec : 0.25
|
||||
feptx_ofdm : 0.25
|
||||
feptx_total : 0.25
|
||||
L1 Tx processing : 0.25
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.35
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.35
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#this is a configuration file
|
||||
#used to build real time processing statistics
|
||||
#for 5G NR phy test (gNB terminate)
|
||||
Title : Processing Time (us)
|
||||
Title : Processing Time (us) from datalog_rt_stats.default.yaml
|
||||
ColNames :
|
||||
- Metric
|
||||
- Average; Max; Count
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Threshold)
|
||||
- Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold)
|
||||
Ref :
|
||||
feprx : 43.0
|
||||
feptx_prec : 13.0
|
||||
@@ -15,20 +15,20 @@ Ref :
|
||||
DLSCH encoding : 118.0
|
||||
L1 Rx processing : 305.0
|
||||
PUSCH inner-receiver : 150.0
|
||||
PUSCH decoding : 2200.0
|
||||
Schedule Response : 30.0
|
||||
DL & UL scheduling timing : 10.0
|
||||
UL Indication : 40.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
|
||||
Schedule Response : 1.25
|
||||
DL & UL scheduling timing : 1.25
|
||||
UL Indication : 1.25
|
||||
Schedule Response : 3.0
|
||||
DL & UL scheduling timing : 6.0
|
||||
UL Indication : 3.0
|
||||
Slot Indication : 7.0
|
||||
DeviationThreshold :
|
||||
feprx : 0.25
|
||||
feptx_prec : 0.25
|
||||
feptx_ofdm : 0.25
|
||||
feptx_total : 0.25
|
||||
L1 Tx processing : 0.25
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.50
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.50
|
||||
|
||||
+4
-2
@@ -1179,8 +1179,10 @@ class RANManagement():
|
||||
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][3])> datalog_rt_stats['Threshold'][k]: #condition for fail : avg/ref is greater than the fixed threshold
|
||||
logging.debug('\u001B[1;30;43m datalog_rt_stats metric ' + k + '=' + datalog_rt_stats['Data'][k][3] + ' > threshold ' + str(datalog_rt_stats['Threshold'][k]) + ' \u001B[0m')
|
||||
valnorm = float(datalog_rt_stats['Data'][k][3])
|
||||
dev = datalog_rt_stats['DeviationThreshold'][k]
|
||||
if valnorm > 1.0 + dev or valnorm < 1.0 - dev: # condition for fail : avg/ref deviates by more than "deviation threshold"
|
||||
logging.debug(f'\u001B[1;30;43m normalized datalog_rt_stats metric {k}={valnorm} deviates by more than {dev}\u001B[0m')
|
||||
RealTimeProcessingIssue = True
|
||||
else:
|
||||
statMsg = 'No real time stats found in the log file\n'
|
||||
|
||||
@@ -24,9 +24,9 @@ gnb :
|
||||
DLSCH encoding:
|
||||
L1 Rx processing:
|
||||
PUSCH inner-receiver:
|
||||
PUSCH decoding:
|
||||
DL & UL scheduling timing:
|
||||
UL Indication:
|
||||
Slot Indication:
|
||||
graph :
|
||||
page1:
|
||||
dlsch_err:
|
||||
@@ -44,6 +44,6 @@ gnb :
|
||||
rt.L1 Rx processing:
|
||||
page4:
|
||||
rt.PUSCH inner-receiver:
|
||||
rt.PUSCH decoding:
|
||||
rt.DL & UL scheduling timing:
|
||||
rt.UL Indication:
|
||||
rt.Slot Indication:
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<!--
|
||||
|
||||
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The OpenAirInterface Software Alliance licenses this file to You under
|
||||
the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.openairinterface.org/?page_id=698
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
contact@openairinterface.org
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>gNB-PHY-Test-100-2x2</htmlTabRef>
|
||||
<htmlTabName>Timing phytest 100 MHz 2x2</htmlTabName>
|
||||
<htmlTabIcon>tasks</htmlTabIcon>
|
||||
<repeatCount>1</repeatCount>
|
||||
<TestCaseRequestedList>
|
||||
100000 390101 000001 390109 200000
|
||||
</TestCaseRequestedList>
|
||||
<TestCaseExclusionList></TestCaseExclusionList>
|
||||
<testCase id="100000">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Disable Sleep States</desc>
|
||||
<node>caracal</node>
|
||||
<command>sudo cpupower idle-set -D 0</command>
|
||||
</testCase>
|
||||
<testCase id="200000">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Enable Sleep States</desc>
|
||||
<node>caracal</node>
|
||||
<command>sudo cpupower idle-set -E</command>
|
||||
</testCase>
|
||||
|
||||
<testCase id="390101">
|
||||
<class>Initialize_eNB</class>
|
||||
<desc>Initialize gNB USRP</desc>
|
||||
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.273prb.usrpn300.phytest-dora.conf --phy-test -q -U 787200 -T 273 -t 23 -D 130175 -m 23 -M 273 -l 2 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
|
||||
<rt_stats_cfg>datalog_rt_stats.100.2x2.yaml</rt_stats_cfg>
|
||||
<air_interface>NR</air_interface>
|
||||
<USRP_IPAddress>192.168.20.2</USRP_IPAddress>
|
||||
<cmd_prefix>numactl --cpunodebind=netdev:enp94s0f0np0 --membind=netdev:enp94s0f0np0</cmd_prefix>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000001">
|
||||
<class>IdleSleep</class>
|
||||
<desc>Sleep</desc>
|
||||
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
|
||||
</testCase>
|
||||
|
||||
|
||||
<testCase id="390109">
|
||||
<class>Terminate_eNB</class>
|
||||
<desc>Terminate gNB</desc>
|
||||
<air_interface>NR</air_interface>
|
||||
</testCase>
|
||||
|
||||
</testCaseList>
|
||||
@@ -504,7 +504,7 @@ function main() {
|
||||
# Doxygen Support #
|
||||
###################
|
||||
if [ "$BUILD_DOXYGEN" = "1" ] ; then
|
||||
echo_info "Built Doxygen based documentation. The documentation file is located here: $OPENAIR_DIR/$BUILD_DIR/build/html/index.html"
|
||||
echo_info "Built Doxygen based documentation. The documentation file is located here: $DIR/$BUILD_DIR/build/doc/html/index.html"
|
||||
fi
|
||||
|
||||
# TODO: once we got the CMakeLists.txt file done for the ORAN files, remove the following lines
|
||||
|
||||
@@ -107,6 +107,8 @@ if (xran_VERSION_STRING STREQUAL "oran_e_maintenance_release_v1.0")
|
||||
set(xran_VERSION 5.1.0)
|
||||
elseif (xran_VERSION_STRING STREQUAL "oran_e_maintenance_release_v1.1")
|
||||
set(xran_VERSION 5.1.1)
|
||||
elseif (xran_VERSION_STRING STREQUAL "oran_e_maintenance_release_v1.2")
|
||||
set(xran_VERSION 5.1.2)
|
||||
endif()
|
||||
unset(xran_VERSION_LINE)
|
||||
unset(xran_VERSION_STRING)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h
|
||||
index 7508117..a93c085 100644
|
||||
index 7508117..0dbe0bd 100644
|
||||
--- a/fhi_lib/app/src/common.h
|
||||
+++ b/fhi_lib/app/src/common.h
|
||||
@@ -28,7 +28,7 @@
|
||||
@@ -7,12 +7,12 @@ index 7508117..a93c085 100644
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
-#define VERSIONX "oran_e_maintenance_release_v1.0"
|
||||
+#define VERSIONX "oran_e_maintenance_release_v1.1"
|
||||
+#define VERSIONX "oran_e_maintenance_release_v1.2"
|
||||
|
||||
#define APP_O_DU 0
|
||||
#define APP_O_RU 1
|
||||
diff --git a/fhi_lib/lib/Makefile b/fhi_lib/lib/Makefile
|
||||
index de141bf..5bcde3d 100644
|
||||
index de141bf..c12b912 100644
|
||||
--- a/fhi_lib/lib/Makefile
|
||||
+++ b/fhi_lib/lib/Makefile
|
||||
@@ -23,11 +23,11 @@ MYCUSTOMSPACE1='------------------------------------------------------------'
|
||||
@@ -30,6 +30,15 @@ index de141bf..5bcde3d 100644
|
||||
OBJDUMP := objdump
|
||||
|
||||
ifeq ($(SHELL),cmd.exe)
|
||||
@@ -57,7 +57,7 @@ endif
|
||||
|
||||
RTE_TARGET ?= x86_64-native-linux-icc
|
||||
|
||||
-RTE_INC := $(shell PKG_CONFIG_PATH=/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk)
|
||||
+RTE_INC := $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH):/usr/lib64/pkgconfig:$(RTE_SDK)/build/meson-uninstalled pkgconf --cflags-only-I libdpdk)
|
||||
API_DIR := $(PROJECT_DIR)/api
|
||||
SRC_DIR := $(PROJECT_DIR)/src
|
||||
ETH_DIR := $(PROJECT_DIR)/ethernet
|
||||
@@ -95,8 +95,7 @@ CPP_SRC = $(SRC_DIR)/xran_compression.cpp \
|
||||
$(SRC_DIR)/xran_bfp_cplane32.cpp \
|
||||
$(SRC_DIR)/xran_bfp_cplane64.cpp \
|
||||
@@ -117,10 +126,18 @@ index 7d3afc5..3e00c5a 100644
|
||||
uint16_t *num_prbu,
|
||||
uint16_t *start_prbu,
|
||||
diff --git a/fhi_lib/lib/ethernet/ethdi.c b/fhi_lib/lib/ethernet/ethdi.c
|
||||
index b6ba257..74b3c26 100644
|
||||
index b6ba257..b53325f 100644
|
||||
--- a/fhi_lib/lib/ethernet/ethdi.c
|
||||
+++ b/fhi_lib/lib/ethernet/ethdi.c
|
||||
@@ -479,11 +479,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg,
|
||||
@@ -335,6 +335,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg,
|
||||
uint16_t count;
|
||||
|
||||
char *argv[] = { name, core_mask, "-n2", iova_mode, socket_mem, socket_limit, "--proc-type=auto",
|
||||
+ "--no-telemetry",
|
||||
"--file-prefix", name, "-a0000:00:00.0", bbdev_wdev, bbdev_vdev};
|
||||
|
||||
|
||||
@@ -479,11 +480,13 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg,
|
||||
ctx->tx_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING_TRX,
|
||||
rte_lcore_to_socket_id(*lcore_id), RING_F_SC_DEQ);
|
||||
PANIC_ON(ctx->tx_ring[i] == NULL, "failed to allocate rx ring");
|
||||
@@ -134,7 +151,7 @@ index b6ba257..74b3c26 100644
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -553,7 +555,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg,
|
||||
@@ -553,7 +556,7 @@ xran_ethdi_init_dpdk_io(char *name, const struct xran_io_cfg *io_cfg,
|
||||
ctx->up_dl_pkt_gen_ring[i] = rte_ring_create(ring_name, NUM_MBUFS_RING,
|
||||
rte_lcore_to_socket_id(*lcore_id), /*RING_F_SC_DEQ*/0);
|
||||
PANIC_ON(ctx->up_dl_pkt_gen_ring[i] == NULL, "failed to allocate dl gen ring");
|
||||
|
||||
@@ -58,11 +58,12 @@ sudo ./program_uicc --adm 12345678 --imsi 001010000000001 --isdn 00000001 --acc
|
||||
|
||||
### Build UHD from source
|
||||
```bash
|
||||
sudo apt install -y libboost-all-dev libusb-1.0-0-dev doxygen python3-docutils python3-mako python3-numpy python3-requests python3-ruamel.yaml python3-setuptools cmake build-essential
|
||||
# https://files.ettus.com/manual/page_build_guide.html
|
||||
sudo apt install -y autoconf automake build-essential ccache cmake cpufrequtils doxygen ethtool g++ git inetutils-tools libboost-all-dev libncurses5 libncurses5-dev libusb-1.0-0 libusb-1.0-0-dev libusb-dev python3-dev python3-mako python3-numpy python3-requests python3-scipy python3-setuptools python3-ruamel.yaml
|
||||
|
||||
git clone https://github.com/EttusResearch/uhd.git ~/uhd
|
||||
cd ~/uhd
|
||||
git checkout v4.5.0.0
|
||||
git checkout v4.6.0.0
|
||||
cd host
|
||||
mkdir build
|
||||
cd build
|
||||
@@ -87,9 +88,7 @@ cd ~/openairinterface5g/cmake_targets
|
||||
./build_oai -I
|
||||
|
||||
# Build OAI gNB
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets
|
||||
cd ~/openairinterface5g/cmake_targets
|
||||
./build_oai -w USRP --ninja --gNB -C
|
||||
```
|
||||
|
||||
@@ -106,24 +105,18 @@ docker compose up -d
|
||||
|
||||
### USRP B210
|
||||
```bash
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --sa -E --continuous-tx
|
||||
```
|
||||
### USRP N300
|
||||
```bash
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf --sa --usrp-tx-thread-config 1
|
||||
```
|
||||
|
||||
### USRP X300
|
||||
```bash
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf --sa --usrp-tx-thread-config 1 -E --continuous-tx
|
||||
```
|
||||
|
||||
|
||||
@@ -58,16 +58,8 @@ rm -r ~/openairinterface5g-develop-doc-tutorial_resources-oai-cn5g ~/oai-cn5g.zi
|
||||
## 2.3 Pull OAI CN5G docker images
|
||||
|
||||
```bash
|
||||
docker pull mysql:8.0
|
||||
docker pull oaisoftwarealliance/oai-amf:develop
|
||||
docker pull oaisoftwarealliance/oai-nrf:develop
|
||||
docker pull oaisoftwarealliance/oai-smf:develop
|
||||
docker pull oaisoftwarealliance/oai-udr:develop
|
||||
docker pull oaisoftwarealliance/oai-udm:develop
|
||||
docker pull oaisoftwarealliance/oai-ausf:develop
|
||||
docker pull oaisoftwarealliance/oai-spgwu-tiny:develop
|
||||
docker pull oaisoftwarealliance/trf-gen-cn5g:jammy
|
||||
docker pull oaisoftwarealliance/ims:latest
|
||||
cd ~/oai-cn5g
|
||||
docker compose pull
|
||||
```
|
||||
|
||||
# 3. Run OAI CN5G
|
||||
|
||||
@@ -46,11 +46,12 @@ Please install and configure OAI CN5G as described here:
|
||||
|
||||
### Build UHD from source
|
||||
```bash
|
||||
sudo apt install -y libboost-all-dev libusb-1.0-0-dev doxygen python3-docutils python3-mako python3-numpy python3-requests python3-ruamel.yaml python3-setuptools cmake build-essential
|
||||
# https://files.ettus.com/manual/page_build_guide.html
|
||||
sudo apt install -y autoconf automake build-essential ccache cmake cpufrequtils doxygen ethtool g++ git inetutils-tools libboost-all-dev libncurses5 libncurses5-dev libusb-1.0-0 libusb-1.0-0-dev libusb-dev python3-dev python3-mako python3-numpy python3-requests python3-scipy python3-setuptools python3-ruamel.yaml
|
||||
|
||||
git clone https://github.com/EttusResearch/uhd.git ~/uhd
|
||||
cd ~/uhd
|
||||
git checkout v4.5.0.0
|
||||
git checkout v4.6.0.0
|
||||
cd host
|
||||
mkdir build
|
||||
cd build
|
||||
@@ -78,9 +79,7 @@ cd ~/openairinterface5g/cmake_targets
|
||||
sudo apt install -y libforms-dev libforms-bin
|
||||
|
||||
# Build OAI gNB
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets
|
||||
cd ~/openairinterface5g/cmake_targets
|
||||
./build_oai -w USRP --ninja --nrUE --gNB --build-lib "nrscope" -C
|
||||
```
|
||||
|
||||
@@ -97,82 +96,71 @@ docker compose up -d
|
||||
|
||||
### USRP B210
|
||||
```bash
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --sa -E --continuous-tx
|
||||
```
|
||||
### USRP N300
|
||||
```bash
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf --gNBs.[0].min_rxtxtime 6 --sa --usrp-tx-thread-config 1
|
||||
```
|
||||
|
||||
### USRP X300
|
||||
```bash
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf --gNBs.[0].min_rxtxtime 6 --sa --usrp-tx-thread-config 1 -E --continuous-tx
|
||||
```
|
||||
|
||||
### RFsimulator
|
||||
```bash
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa
|
||||
```
|
||||
|
||||
### RFsimulator in FR2
|
||||
```bash
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.32prb.usrpx410.conf --rfsim
|
||||
```
|
||||
|
||||
# 5. OAI UE
|
||||
|
||||
## 5.1 SIM Card
|
||||
Edit openair3/UICC/usim_interface.c
|
||||
```bash
|
||||
#define UICC_PARAMS_DESC {\
|
||||
{"imsi", "USIM IMSI\n", 0, strptr:&(uicc->imsiStr), defstrval:"001010000000001", TYPE_STRING, 0 },\
|
||||
{"nmc_size" "number of digits in NMC", 0, iptr:&(uicc->nmc_size), defintval:2, TYPE_INT, 0 },\
|
||||
{"key", "USIM Ki\n", 0, strptr:&(uicc->keyStr), defstrval:"fec86ba6eb707ed08905757b1bb44b8f", TYPE_STRING, 0 },\
|
||||
{"opc", "USIM OPc\n", 0, strptr:&(uicc->opcStr), defstrval:"c42449363bbad02b66d16bc975d77cc1", TYPE_STRING, 0 },\
|
||||
{"amf", "USIM amf\n", 0, strptr:&(uicc->amfStr), defstrval:"8000", TYPE_STRING, 0 },\
|
||||
{"sqn", "USIM sqn\n", 0, strptr:&(uicc->sqnStr), defstrval:"000000", TYPE_STRING, 0 },\
|
||||
{"dnn", "UE dnn (apn)\n", 0, strptr:&(uicc->dnnStr), defstrval:"oai", TYPE_STRING, 0 },\
|
||||
{"nssai_sst", "UE nssai\n", 0, iptr:&(uicc->nssai_sst), defintval:1, TYPE_INT, 0 }, \
|
||||
{"nssai_sd", "UE nssai\n", 0, iptr:&(uicc->nssai_sd), defintval:0xffffff, TYPE_INT, 0 }, \
|
||||
};
|
||||
```
|
||||
|
||||
## 5.2 Testing OAI nrUE with USRP B210
|
||||
|
||||
## 5.1 Run OAI nrUE
|
||||
### USRP B210
|
||||
Important notes:
|
||||
- This should be run in a second Ubuntu 22.04 host, other than gNB
|
||||
- It only applies when running OAI gNB with USRP B210
|
||||
|
||||
Run OAI nrUE
|
||||
Run OAI nrUE with USRP B210
|
||||
```bash
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ue-fo-compensation --sa -E --uicc0.imsi 001010000000001
|
||||
```
|
||||
|
||||
## 5.2 Testing OAI nrUE with RFsimulator
|
||||
### RFsimulator
|
||||
Important notes:
|
||||
- This should be run on the same host as the OAI gNB
|
||||
- It only applies when running OAI gNB with RFsimulator
|
||||
|
||||
Run OAI nrUE with RFsimulator
|
||||
```bash
|
||||
cd ~/openairinterface5g
|
||||
source oaienv
|
||||
cd cmake_targets/ran_build/build
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001 --rfsimulator.serveraddr 127.0.0.1
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --sa --uicc0.imsi 001010000000001 --rfsim
|
||||
```
|
||||
|
||||
### 5.2.1 Ping test
|
||||
- UE host
|
||||
### RFsimulator in FR2
|
||||
Important notes:
|
||||
- This should be run on the same host as the OAI gNB
|
||||
- It only applies when running OAI gNB with RFsimulator in FR2
|
||||
|
||||
Run OAI nrUE with RFsimulator in FR2
|
||||
```bash
|
||||
cd ~/openairinterface5g/cmake_targets/ran_build/build
|
||||
sudo ./nr-uesoftmodem -r 32 --numerology 3 --band 257 -C 27533280000 --sa --uicc0.imsi 001010000000001 --ssb 72 --rfsim
|
||||
```
|
||||
|
||||
## 5.2 End-to-end connectivity test
|
||||
- Ping test from the UE host to the CN5G
|
||||
```bash
|
||||
ping 192.168.70.135 -I oaitun_ue1
|
||||
```
|
||||
|
||||
+165
-74
@@ -30,11 +30,12 @@ The hardware on which we have tried this tutorial:
|
||||
|
||||
NICs we have tested so far:
|
||||
|
||||
|Vendor |Firmware Version |
|
||||
|------------|------------------------|
|
||||
|Intel X710 |9.20 0x8000d95e 22.0.9 |
|
||||
|Intel E810 |4.00 0x8001184e 1.3236.0|
|
||||
|Intel XXV710|6.02 0x80003888 |
|
||||
|Vendor |Firmware Version |
|
||||
|---------------|------------------------|
|
||||
|Intel X710 |9.20 0x8000d95e 22.0.9 |
|
||||
|Intel E810-XXV |4.00 0x8001184e 1.3236.0|
|
||||
|E810-C |4.20 0x8001784e 22.0.9 |
|
||||
|Intel XXV710 |6.02 0x80003888 |
|
||||
|
||||
PTP enabled switches and grandmaster clock we have in are lab:
|
||||
|
||||
@@ -44,8 +45,17 @@ PTP enabled switches and grandmaster clock we have in are lab:
|
||||
|Fibrolan Falcon-RX/812/G|8.0.25.4 |
|
||||
|Qulsar Qg2 (Grandmaster)|12.1.27 |
|
||||
|
||||
**S-Plane synchronization is mandatory.** S-plane support is done via `ptp4l`
|
||||
and `phc2sys`.
|
||||
|
||||
Radio units we are testing/integrating:
|
||||
| Software | Software Version |
|
||||
|-----------|------------------|
|
||||
| `ptp4l` | 3.1.1 |
|
||||
| `phc2sys` | 3.1.1 |
|
||||
|
||||
We have only verified LLS-C3 configuration in our lab, i.e. using an external
|
||||
grandmaster, a switch as a boundary clock, and the gNB/DU and RU. We haven't
|
||||
tested any RU without S-plane. Radio units we are testing/integrating:
|
||||
|
||||
|Vendor |Software Version |
|
||||
|-----------|-----------------|
|
||||
@@ -74,14 +84,14 @@ Tested libxran releases:
|
||||
|
||||
Your server could be:
|
||||
|
||||
* One NUMA Node (See [one NUMA node example](#111-one-numa-node)): all the processors are sharing a single memory system.
|
||||
* Two NUMA Node (see [two NUMA node example](#112-two-numa-node)): processors are grouped in 2 memory systems.
|
||||
* One NUMA node (See [one NUMA node example](#111-one-numa-node)): all the processors are sharing a single memory system.
|
||||
* Two NUMA nodes (see [two NUMA nodes example](#112-two-numa-node)): processors are grouped in 2 memory systems.
|
||||
- Usually the even (ie `0,2,4,...`) CPUs are on the 1st socket
|
||||
- And the odd (ie (`1,3,5,...`) CPUs are on the 2nd socket
|
||||
|
||||
DPDK, OAI and kernel threads require to be properly allocated to extract maximum real-time performance for your use case.
|
||||
|
||||
1. **NOTE**: Currently the default OAI 7.2 configuration file requires isolated **CPUs 0,2,4** for DPDK/libXRAN, **CPU 6** for `ru_thread` and **CPU 8** for `L1_rx_thread`. It is preferrable to have all these threads on the same socket.
|
||||
1. **NOTE**: Currently the default OAI 7.2 configuration file requires isolated **CPUs 0,2,4** for DPDK/libXRAN, **CPU 6** for `ru_thread`, **CPU 8** for `L1_rx_thread` and **CPU 10** for `L1_tx_thread`. It is preferrable to have all these threads on the same socket.
|
||||
2. Allocating CPUs to the OAI nr-softmodem is done using the `--thread-pool` option. Allocating 4 CPUs is the minimal configuration but we recommend to allocate at least **8** CPUs. And they can be on a different socket as the DPDK threads.
|
||||
3. And to avoid kernel preempting these allocated CPUs, it is better to force the kernel to use un-allocated CPUs.
|
||||
|
||||
@@ -92,16 +102,17 @@ Let summarize for example on a `32-CPU` single NUMA node system, regardless of t
|
||||
|XRAN DPDK usage |0,2,4 |
|
||||
|OAI `ru_thread` |6 |
|
||||
|OAI `L1_rx_thread` |8 |
|
||||
|OAI `L1_tx_thread` |10 |
|
||||
|OAI `nr-softmodem` |1,3,5,7,9,11,13,15|
|
||||
|kernel |16-31 |
|
||||
|
||||
In below example we have shown the output of `/proc/cmdline` for two different servers, each of them have different number of numa nodes. Be careful in isolating the CPUs in your environment. Apart from CPU allocation there are additional parameters which are important to be present in your boot command.
|
||||
In below example we have shown the output of `/proc/cmdline` for two different servers, each of them have different number of NUMA nodes. Be careful in isolating the CPUs in your environment. Apart from CPU allocation there are additional parameters which are important to be present in your boot command.
|
||||
|
||||
Modifying the `linux` command line usually requires to edit the `/etc/default/grub`, run a `grub` command and reboot the server.
|
||||
|
||||
### One NUMA NODE
|
||||
### One NUMA Node
|
||||
|
||||
Below is the output of `/proc/cmdline` of a single numa node server,
|
||||
Below is the output of `/proc/cmdline` of a single NUMA node server,
|
||||
|
||||
```bash
|
||||
NUMA:
|
||||
@@ -115,9 +126,9 @@ isolcpus=0-15 nohz_full=0-15 rcu_nocbs=0-15 kthread_cpus=16-31 rcu_nocb_poll nos
|
||||
|
||||
Example taken for AMD EPYC 9374F 32-Core Processor
|
||||
|
||||
### Two numa nodes
|
||||
### Two NUMA Nodes
|
||||
|
||||
Below is the output of `/proc/cmdline` of a two numa node server,
|
||||
Below is the output of `/proc/cmdline` of a two NUMA node server,
|
||||
|
||||
```
|
||||
NUMA:
|
||||
@@ -431,7 +442,9 @@ cmake .. -GNinja -DOAI_FHI72=ON -Dxran_LOCATION=$HOME/phy/fhi_lib/lib
|
||||
ninja nr-softmodem oran_fhlib_5g params_libconfig
|
||||
```
|
||||
|
||||
# Configure the RU
|
||||
# Configuration
|
||||
|
||||
## Configure the RU
|
||||
|
||||
Contact the RU vendor to get the configuration manual, and configure the RU
|
||||
appropriately. You can orient on the OAI configuration files mentioned further
|
||||
@@ -439,61 +452,6 @@ below.
|
||||
|
||||
We are evaluating if we can share RU configuration steps.
|
||||
|
||||
# Configure OAI gNB
|
||||
|
||||
Sample configuration files for OAI gNB, specific to the manufacturer of the radio unit, are available at:
|
||||
1. LITE-ON RU: [`gnb.sa.band78.273prb.fhi72.4x4-liteon.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf) (band n78, 273 PRBs, 3.5GHz center freq, 4x4 antenna configuration with 9 bit I/Q samples (compressed) for PUSCH/PDSCH/PRACH, 2-layer DL MIMO, UL SISO)
|
||||
2. Benetel 650 RU: [`gnb.sa.band78.273prb.fhi72.4x2-benetel650.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel650.conf) (band n78, 273 PRBs, 3.5GHz center freq, 4x2 antenna configuration with 9 bit I/Q samples (compressed) for PUSCH/PDSCH/PRACH, 2-layer DL MIMO, UL SISO)
|
||||
3. VVDN RU: [`gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf) (band n77, 273 PRBs, 4.0GHz center freq, 4x4 antenna configuration with 9 bit I/Q samples (compressed) for PUSCH/PDSCH/PRACH, 2-layer DL MIMO, UL SISO)
|
||||
|
||||
## Adapt the OAI-gNB configuration file to your system/workspace
|
||||
|
||||
Edit the sample OAI gNB configuration file and check following parameters:
|
||||
|
||||
* `gNBs` section
|
||||
* The PLMN section shall match the one defined in the AMF
|
||||
* `amf_ip_address` shall be the correct AMF IP address in your system
|
||||
* `GNB_INTERFACE_NAME_FOR_NG_AMF` and `GNB_IPV4_ADDRESS_FOR_NG_AMF` shall match your DU N2 interface name and IP address
|
||||
* `GNB_INTERFACE_NAME_FOR_NGU` and `GNB_IPV4_ADDRESS_FOR_NGU` shall match your DU N3 interface name and IP address
|
||||
* `prach_ConfigurationIndex`
|
||||
* `prach_msg1_FrequencyStart`
|
||||
* Adjust the frequency, bandwidth and SSB position
|
||||
|
||||
* `L1s` section
|
||||
* Set an isolated core for L1 thread `L1_rx_thread_core`, in our environment we are using CPU 8
|
||||
* `phase_compensation` should be set to 0 to disable when it is performed in the RU and set to 1 when it should be performed on the DU side
|
||||
|
||||
* `RUs` section
|
||||
* Set an isolated core for RU thread `ru_thread_core`, in our environment we are using CPU 6
|
||||
|
||||
* `fhi_72` (FrontHaul Interface) section: this config follows the structure
|
||||
that is employed by the xRAN library (`xran_fh_init` and `xran_fh_config`
|
||||
structs in the code):
|
||||
* `dpdk_devices`: PCI addresses of NIC VFs binded to the DPDK
|
||||
* `io_core`: absolute CPU core ID for XRAN library
|
||||
* `worker_cores`: array of absolute CPU core IDs for XRAN library
|
||||
* `du_addr`: DU C- and U-plane MAC-addresses (format `UU:VV:WW:XX:YY:ZZ`,
|
||||
hexadecimal numbers)
|
||||
* `ru_addr`: RU C- and U-plane MAC-addresses (format `UU:VV:WW:XX:YY:ZZ`,
|
||||
hexadecimal numbers)
|
||||
* `mtu`: Maximum Transmission Unit for the RU, specified by RU vendor
|
||||
* `fh_config`: parameters that need to match RU parameters
|
||||
* timing parameters (starting with `T`) depend on the RU: `Tadv_cp_dl` is a
|
||||
single number, the rest pairs of numbers `(x, y)` specifying minimum and
|
||||
maximum delays
|
||||
* `ru_config`: RU-specific configuration:
|
||||
* `iq_width`: Width of DL/UL IQ samples: if 16, no compression, if <16, applies
|
||||
compression
|
||||
* `iq_width_prach`: Width of PRACH IQ samples: if 16, no compression, if <16, applies
|
||||
compression
|
||||
* `fft_size`: size of FFT performed by RU, set to 12 by default
|
||||
* `prach_config`: PRACH-specific configuration
|
||||
* `eAxC_offset`: PRACH antenna offset
|
||||
* `kbar`: the PRACH guard interval, provided in RU
|
||||
|
||||
xRAN SRS reception is not supported. The eAxC offsets for DL/UL are determined
|
||||
from the antenna configuration.
|
||||
|
||||
## Configure Network Interfaces and DPDK VFs
|
||||
|
||||
The 7.2 fronthaul uses the xran library, which requires DPDK. In this step, we
|
||||
@@ -624,13 +582,146 @@ sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci 31:06.1
|
||||
```
|
||||
</details>
|
||||
|
||||
# Start OAI gNB
|
||||
|
||||
## Configure OAI gNB
|
||||
|
||||
Sample configuration files for OAI gNB, specific to the manufacturer of the radio unit, are available at:
|
||||
1. LITE-ON RU: [`gnb.sa.band78.273prb.fhi72.4x4-liteon.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf) (band n78, 273 PRBs, 3.5GHz center freq, 4x4 antenna configuration with 9 bit I/Q samples (compressed) for PUSCH/PDSCH/PRACH, 2-layer DL MIMO, UL SISO)
|
||||
2. Benetel 650 RU: [`gnb.sa.band78.273prb.fhi72.4x2-benetel650.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel650.conf) (band n78, 273 PRBs, 3.5GHz center freq, 4x2 antenna configuration with 9 bit I/Q samples (compressed) for PUSCH/PDSCH/PRACH, 2-layer DL MIMO, UL SISO)
|
||||
3. VVDN RU: [`gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf) (band n77, 273 PRBs, 4.0GHz center freq, 4x4 antenna configuration with 9 bit I/Q samples (compressed) for PUSCH/PDSCH/PRACH, 2-layer DL MIMO, UL SISO)
|
||||
|
||||
Edit the sample OAI gNB configuration file and check following parameters:
|
||||
|
||||
* `gNBs` section
|
||||
* The PLMN section shall match the one defined in the AMF
|
||||
* `amf_ip_address` shall be the correct AMF IP address in your system
|
||||
* `GNB_INTERFACE_NAME_FOR_NG_AMF` and `GNB_IPV4_ADDRESS_FOR_NG_AMF` shall match your DU N2 interface name and IP address
|
||||
* `GNB_INTERFACE_NAME_FOR_NGU` and `GNB_IPV4_ADDRESS_FOR_NGU` shall match your DU N3 interface name and IP address
|
||||
* `prach_ConfigurationIndex`
|
||||
* `prach_msg1_FrequencyStart`
|
||||
* Adjust the frequency, bandwidth and SSB position
|
||||
|
||||
* `L1s` section
|
||||
* Set an isolated core for L1 thread `L1_rx_thread_core`, in our environment we are using CPU 8
|
||||
* Set an isolated core for L1 thread `L1_tx_thread_core`, in our environment we are using CPU 10
|
||||
* `phase_compensation` should be set to 0 to disable when it is performed in the RU and set to 1 when it should be performed on the DU side
|
||||
|
||||
* `RUs` section
|
||||
* Set an isolated core for RU thread `ru_thread_core`, in our environment we are using CPU 6
|
||||
|
||||
* `fhi_72` (FrontHaul Interface) section: this config follows the structure
|
||||
that is employed by the xRAN library (`xran_fh_init` and `xran_fh_config`
|
||||
structs in the code):
|
||||
* `dpdk_devices`: PCI addresses of NIC VFs binded to the DPDK
|
||||
* `system_core`: absolute CPU core ID for DPDK control threads
|
||||
(`rte_mp_handle`, `eal-intr-thread`, `iavf-event-thread`)
|
||||
* `io_core`: absolute CPU core ID for XRAN library, it should be an isolated core, in our environment we are using CPU 4
|
||||
* `worker_cores`: array of absolute CPU core IDs for XRAN library, they should be isolated cores, in our environment we are using CPU 2
|
||||
* `du_addr`: DU C- and U-plane MAC-addresses (format `UU:VV:WW:XX:YY:ZZ`,
|
||||
hexadecimal numbers)
|
||||
* `ru_addr`: RU C- and U-plane MAC-addresses (format `UU:VV:WW:XX:YY:ZZ`,
|
||||
hexadecimal numbers)
|
||||
* `mtu`: Maximum Transmission Unit for the RU, specified by RU vendor
|
||||
* `fh_config`: parameters that need to match RU parameters
|
||||
* timing parameters (starting with `T`) depend on the RU: `Tadv_cp_dl` is a
|
||||
single number, the rest pairs of numbers `(x, y)` specifying minimum and
|
||||
maximum delays
|
||||
* `ru_config`: RU-specific configuration:
|
||||
* `iq_width`: Width of DL/UL IQ samples: if 16, no compression, if <16, applies
|
||||
compression
|
||||
* `iq_width_prach`: Width of PRACH IQ samples: if 16, no compression, if <16, applies
|
||||
compression
|
||||
* `fft_size`: size of FFT performed by RU, set to 12 by default
|
||||
* `prach_config`: PRACH-specific configuration
|
||||
* `eAxC_offset`: PRACH antenna offset
|
||||
* `kbar`: the PRACH guard interval, provided in RU
|
||||
|
||||
Layer mapping (eAxC offsets) happens as follows:
|
||||
- For PUSCH/PDSCH, the layers are mapped to `[0,1,...,N-1]` where `N` is the
|
||||
respective RX/TX number of antennas.
|
||||
- For PRACH, the layers are mapped to `[No,No+1,...No+N-1]` where No is the
|
||||
`fhi_72.fh_config.[0].prach_config.eAxC_offset` and `N` the number of receive
|
||||
antennas.
|
||||
|
||||
xRAN SRS reception is not supported.
|
||||
|
||||
# Start and Operation of OAI gNB
|
||||
|
||||
Run the `nr-softmodem` from the build directory:
|
||||
```bash
|
||||
cd ran_build/build
|
||||
|
||||
cd ~/openairinterface5g/ran_build/build
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/oran.fh.band78.fr1.273PRB.conf --sa --reorder-thread-disable 1 --thread-pool <list of non isolated cpus>
|
||||
```
|
||||
|
||||
For example if you have two numa nodes (for example 18 CPU per socket) in your system and odd cores are non isolated then you can put the thread-pool on `1,3,5,7,9,11,13,15`. Else if you have 1 numa node either you can use isolated cores or non isolated. Just make sure that isolated cores are not the ones defined earlier.
|
||||
You have to set the thread pool option to non-isolated CPUs, since the thread
|
||||
pool is used for L1 processing which should not interfere with DPDK threads.
|
||||
For example if you have two NUMA nodes in your system (for example 18 CPUs per
|
||||
socket) and odd cores are non-isolated, then you can put the thread-pool on
|
||||
`1,3,5,7,9,11,13,15`. On the other hand, if you have one NUMA node, you can use
|
||||
either isolated cores or non isolated cores, but make sure that isolated cores
|
||||
are not the ones defined earlier for DPDK/xran.
|
||||
|
||||
<details>
|
||||
<summary>Once the gNB runs, you should see counters for PDSCH/PUSCH/PRACH per
|
||||
antenna port, as follows (4x2 configuration):</summary>
|
||||
|
||||
```
|
||||
[NR_PHY] [o-du 0][rx 24604 pps 24520 kbps 455611][tx 126652 pps 126092 kbps 2250645][Total Msgs_Rcvd 24604]
|
||||
[NR_PHY] [o_du0][pusch0 10766 prach0 1536]
|
||||
[NR_PHY] [o_du0][pusch1 10766 prach1 1536]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
The first line show RX/TX packet counters, i.e., packets received from the RU
|
||||
(RX), and sent to the RU (TX). In the second and third line, it shows the
|
||||
counters for the PUSCH and PRACH ports (2 receive antennas, so two counters
|
||||
each). These numbers should be equal, otherwise it indicates that you don't
|
||||
receive enough packets on either port.
|
||||
|
||||
<details>
|
||||
<summary>If you see many zeroes, then it means that OAI does not receive
|
||||
packets on the fronthaul from the RU (RX is almost 0, all PUSCH/PRACH counters
|
||||
are 0).</summary>
|
||||
|
||||
```
|
||||
[NR_PHY] [o-du 0][rx 2 pps 0 kbps 0][tx 1020100 pps 127488 kbps 4717971][Total Msgs_Rcvd 2]
|
||||
[NR_PHY] [o_du0][pusch0 0 prach0 0]
|
||||
[NR_PHY] [o_du0][pusch1 0 prach1 0]
|
||||
[NR_PHY] [o_du0][pusch2 0 prach2 0]
|
||||
[NR_PHY] [o_du0][pusch3 0 prach3 0]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
In this case, please make sure that the O-RU has been configured with the right
|
||||
ethernet address of the gNB, and has been activated. You might enable port
|
||||
mirroring at your switch to capture the fronthaul packets: check that you see
|
||||
(1) packets at all (2) they have the right ethernet address (3) the right VLAN
|
||||
tag. Although we did not test this, you might make use of the [DPDK packet
|
||||
capture feature](https://doc.dpdk.org/guides/howto/packet_capture_framework.html)
|
||||
|
||||
<details>
|
||||
<summary>If you see messages about `Received time doesn't correspond to the
|
||||
time we think it is` or `Jump in frame counter`, the S-plane is not working.</summary>
|
||||
|
||||
```
|
||||
[PHY] Received Time doesn't correspond to the time we think it is (slot mismatch, received 480.5, expected 475.8)
|
||||
[PHY] Received Time doesn't correspond to the time we think it is (frame mismatch, 480.5 , expected 475.5)
|
||||
[PHY] Jump in frame counter last_frame 480 => 519, slot 19
|
||||
[PHY] Received Time doesn't correspond to the time we think it is (slot mismatch, received 519.19, expected 480.12)
|
||||
[PHY] Received Time doesn't correspond to the time we think it is (frame mismatch, 519.19 , expected 480.19)
|
||||
[PHY] Received Time doesn't correspond to the time we think it is (slot mismatch, received 520.1, expected 520.0)
|
||||
```
|
||||
|
||||
You can see that the frame numbers jump around, by 5-40 frames (corresponding
|
||||
to 50-400ms!). This indicates the gNB receives packets on the fronthaul that
|
||||
don't match its internal time, and the synchronization between gNB and RU is
|
||||
not working!
|
||||
|
||||
</details>
|
||||
|
||||
In this case, you should reverify that `ptp4l` and `phc2sys` are working, e.g.,
|
||||
do not do any jumps (during the last hour). While an occasional jump is not
|
||||
necessarily problematic for the gNB, many such messages mean that the system is
|
||||
not working, and UEs might not be able to attach or reach good performance.
|
||||
|
||||
@@ -59,6 +59,23 @@ nfs:
|
||||
n4:
|
||||
interface_name: eth0
|
||||
port: 8805
|
||||
upf:
|
||||
host: oai-upf
|
||||
sbi:
|
||||
port: 8080
|
||||
api_version: v1
|
||||
interface_name: eth0
|
||||
n3:
|
||||
interface_name: eth0
|
||||
port: 2152
|
||||
n4:
|
||||
interface_name: eth0
|
||||
port: 8805
|
||||
n6:
|
||||
interface_name: eth0
|
||||
n9:
|
||||
interface_name: eth0
|
||||
port: 2152
|
||||
udm:
|
||||
host: oai-udm
|
||||
sbi:
|
||||
@@ -94,6 +111,16 @@ database:
|
||||
generate_random: true
|
||||
connection_timeout: 300 # seconds
|
||||
|
||||
## general single_nssai configuration
|
||||
## Defines YAML anchors, which are reused in the config file
|
||||
snssais:
|
||||
- &embb_slice1
|
||||
sst: 1
|
||||
- &embb_slice2
|
||||
sst: 1
|
||||
- &embb_slice3
|
||||
sst: 1
|
||||
|
||||
############## NF-specific configuration
|
||||
amf:
|
||||
pid_directory: "/var/run"
|
||||
@@ -110,7 +137,7 @@ amf:
|
||||
served_guami_list:
|
||||
- mcc: 001
|
||||
mnc: 01
|
||||
amf_region_id: 80
|
||||
amf_region_id: 01
|
||||
amf_set_id: 001
|
||||
amf_pointer: 01
|
||||
plmn_support_list:
|
||||
@@ -118,7 +145,9 @@ amf:
|
||||
mnc: 01
|
||||
tac: 0x0001
|
||||
nssai:
|
||||
- sst: 1
|
||||
- *embb_slice1
|
||||
- *embb_slice2
|
||||
- *embb_slice3
|
||||
supported_integrity_algorithms:
|
||||
- "NIA1"
|
||||
- "NIA2"
|
||||
@@ -134,7 +163,7 @@ smf:
|
||||
use_local_pcc_rules: yes # Use infos from local_pcc_rules or from PCF
|
||||
# we resolve from NRF, this is just to configure usage_reporting
|
||||
upfs:
|
||||
- host: oai-spgwu
|
||||
- host: oai-upf
|
||||
config:
|
||||
enable_usage_reporting: no
|
||||
ue_dns:
|
||||
@@ -145,40 +174,68 @@ smf:
|
||||
ims:
|
||||
pcscf_ipv4: "192.168.70.139"
|
||||
pcscf_ipv6: "fe80::7915:f408:1787:db8b"
|
||||
# the DNN you configure here should be configured in "dnns"
|
||||
# the DNN you configure here should be configured in "dnns"
|
||||
# follows the SmfInfo datatype from 3GPP TS 29.510
|
||||
smf_info:
|
||||
sNssaiSmfInfoList:
|
||||
- sNssai: *embb_slice1
|
||||
dnnSmfInfoList:
|
||||
- dnn: "oai"
|
||||
- sNssai: *embb_slice2
|
||||
dnnSmfInfoList:
|
||||
- dnn: "openairinterface"
|
||||
- sNssai: *embb_slice3
|
||||
dnnSmfInfoList:
|
||||
- dnn: "ims"
|
||||
local_subscription_infos:
|
||||
- single_nssai:
|
||||
sst: 1
|
||||
- single_nssai: *embb_slice1
|
||||
dnn: "oai"
|
||||
qos_profile:
|
||||
5qi: 9
|
||||
session_ambr_ul: "10Gbps"
|
||||
session_ambr_dl: "10Gbps"
|
||||
- single_nssai:
|
||||
sst: 1
|
||||
- single_nssai: *embb_slice2
|
||||
dnn: "openairinterface"
|
||||
qos_profile:
|
||||
5qi: 9
|
||||
session_ambr_ul: "10Gbps"
|
||||
session_ambr_dl: "10Gbps"
|
||||
- single_nssai:
|
||||
sst: 1
|
||||
- single_nssai: *embb_slice3
|
||||
dnn: "ims"
|
||||
qos_profile:
|
||||
5qi: 9
|
||||
session_ambr_ul: "10Gbps"
|
||||
session_ambr_dl: "10Gbps"
|
||||
|
||||
upf:
|
||||
support_features:
|
||||
enable_bpf_datapath: no # If "on": BPF is used as datapath else simpleswitch is used, DEFAULT= off
|
||||
enable_snat: yes # If "on": Source natting is done for UE, DEFAULT= off
|
||||
remote_n6_gw: localhost # Dummy host since simple-switch does not use N6 GW
|
||||
smfs:
|
||||
- host: oai-smf # To be used for PFCP association in case of no-NRF
|
||||
upf_info:
|
||||
sNssaiUpfInfoList:
|
||||
- sNssai: *embb_slice1
|
||||
dnnUpfInfoList:
|
||||
- dnn: "oai"
|
||||
- sNssai: *embb_slice2
|
||||
dnnUpfInfoList:
|
||||
- dnn: "openairinterface"
|
||||
- sNssai: *embb_slice3
|
||||
dnnUpfInfoList:
|
||||
- dnn: "ims"
|
||||
|
||||
## DNN configuration
|
||||
dnns:
|
||||
- dnn: "oai"
|
||||
pdu_session_type: "IPV4"
|
||||
ipv4_subnet: "12.1.1.2/24"
|
||||
ipv4_subnet: "10.0.0.0/24"
|
||||
- dnn: "openairinterface"
|
||||
pdu_session_type: "IPV4V6"
|
||||
ipv4_subnet: "12.1.2.2/24"
|
||||
ipv4_subnet: "10.0.1.0/24"
|
||||
ipv6_prefix: "2001:1:2::/64"
|
||||
- dnn: "ims"
|
||||
pdu_session_type: "IPV4V6"
|
||||
ipv4_subnet: "12.1.9.2/24"
|
||||
ipv4_subnet: "10.0.9.0/24"
|
||||
ipv6_prefix: "2001:1:2::/64"
|
||||
|
||||
@@ -22,7 +22,7 @@ services:
|
||||
ipv4_address: 192.168.70.131
|
||||
|
||||
ims:
|
||||
container_name: "asterisk-ims"
|
||||
container_name: "ims"
|
||||
image: oaisoftwarealliance/ims:latest
|
||||
volumes:
|
||||
- ./conf/sip.conf:/etc/asterisk/sip.conf
|
||||
@@ -129,40 +129,16 @@ services:
|
||||
networks:
|
||||
public_net:
|
||||
ipv4_address: 192.168.70.133
|
||||
oai-spgwu:
|
||||
container_name: "oai-spgwu"
|
||||
image: oaisoftwarealliance/oai-spgwu-tiny:develop
|
||||
oai-upf:
|
||||
container_name: "oai-upf"
|
||||
image: oaisoftwarealliance/oai-upf:develop
|
||||
expose:
|
||||
- 2152/udp
|
||||
- 8805/udp
|
||||
- 8080/tcp
|
||||
# TODO: oai-spgwu-tiny will not support the new common yaml config file feature
|
||||
# waiting for the new oai-upf NF
|
||||
volumes:
|
||||
- ./conf/config.yaml:/openair-upf/etc/config.yaml
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
- SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP=eth0
|
||||
- SGW_INTERFACE_NAME_FOR_SX=eth0
|
||||
- PGW_INTERFACE_NAME_FOR_SGI=eth0
|
||||
- NETWORK_UE_NAT_OPTION=yes
|
||||
- NETWORK_UE_IP=12.1.0.0/16
|
||||
- ENABLE_5G_FEATURES=yes
|
||||
- REGISTER_NRF=yes
|
||||
- USE_FQDN_NRF=yes
|
||||
- UPF_FQDN_5G=oai-spgwu
|
||||
- NRF_IPV4_ADDRESS=192.168.70.130
|
||||
- NRF_FQDN=oai-nrf
|
||||
# Mandatory to set the NRF PORT to 8080 (it is set to default to 80 otherwise)
|
||||
- HTTP_VERSION=2
|
||||
- NRF_PORT=8080
|
||||
# Slice 0 (1, 0xFFFFFF)
|
||||
- NSSAI_SST_0=1
|
||||
- DNN_0=oai
|
||||
# Slice 1 (1, 0xFFFFFF)
|
||||
- NSSAI_SST_1=1
|
||||
- DNN_1=openairinterface
|
||||
# Slice 2 (1, 0xFFFFFF)
|
||||
- NSSAI_SST_2=1
|
||||
- DNN_2=ims
|
||||
depends_on:
|
||||
- oai-nrf
|
||||
- oai-smf
|
||||
@@ -181,10 +157,10 @@ services:
|
||||
container_name: oai-ext-dn
|
||||
image: oaisoftwarealliance/trf-gen-cn5g:jammy
|
||||
entrypoint: /bin/bash -c \
|
||||
"ip route add 12.1.0.0/16 via 192.168.70.134 dev eth0; ip route; sleep infinity"
|
||||
"ip route add 10.0.0.0/16 via 192.168.70.134 dev eth0; ip route; sleep infinity"
|
||||
command: ["/bin/bash", "-c", "trap : SIGTERM SIGINT; sleep infinity & wait"]
|
||||
healthcheck:
|
||||
test: /bin/bash -c "ip r | grep 12.1.0"
|
||||
test: /bin/bash -c "ip r | grep 10.0.0"
|
||||
interval: 5s
|
||||
timeout: 2s
|
||||
retries: 10
|
||||
|
||||
@@ -57,7 +57,8 @@ static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args)
|
||||
|
||||
// Only 1 instances is supported in one executable
|
||||
// Advice: run multiple executables to have multiple instances
|
||||
const e1ap_upcp_inst_t *e1inst = getCxtE1(CUuniqInstance);
|
||||
const instance_t e1_inst = 0;
|
||||
const e1ap_upcp_inst_t *e1inst = getCxtE1(e1_inst);
|
||||
|
||||
const int nb_id = e1inst->gnb_id;
|
||||
const int cu_up_id = e1inst->cuup.setupReq.gNB_cu_up_id;
|
||||
@@ -155,6 +156,10 @@ int main(int argc, char **argv)
|
||||
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
|
||||
}
|
||||
logInit();
|
||||
#ifndef PACKAGE_VERSION
|
||||
# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
|
||||
#endif
|
||||
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
|
||||
set_softmodem_sighandler();
|
||||
itti_init(TASK_MAX, tasks_info);
|
||||
int rc;
|
||||
|
||||
+93
-240
@@ -52,6 +52,8 @@
|
||||
#include "PHY/MODULATION/nr_modulation.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h"
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
|
||||
#include "LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
|
||||
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
||||
@@ -109,42 +111,70 @@ time_stats_t softmodem_stats_rx_sf; // total rx time
|
||||
#define TICK_TO_US(ts) (ts.trials==0?0:ts.diff/ts.trials)
|
||||
#define L1STATSSTRLEN 16384
|
||||
|
||||
|
||||
void tx_func(void *param)
|
||||
static void tx_func(void *param)
|
||||
{
|
||||
processingData_L1tx_t *info = (processingData_L1tx_t *) param;
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
|
||||
int frame_tx = info->frame;
|
||||
int slot_tx = info->slot;
|
||||
int cumul_samples = gNB->frame_parms.get_samples_per_slot(0, &gNB->frame_parms);
|
||||
int i = 1;
|
||||
for (; i < gNB->frame_parms.slots_per_subframe / 2; i++)
|
||||
cumul_samples += gNB->frame_parms.get_samples_per_slot(i, &gNB->frame_parms);
|
||||
int samples = cumul_samples / i;
|
||||
int absslot_tx = info->timestamp_tx / samples;
|
||||
int absslot_rx = absslot_tx - gNB->RU_list[0]->sl_ahead;
|
||||
int rt_prof_idx = absslot_rx % RT_PROF_DEPTH;
|
||||
start_meas(&gNB->phy_proc_tx);
|
||||
int frame_rx = info->frame_rx;
|
||||
int slot_rx = info->slot_rx;
|
||||
int absslot_tx = info->timestamp_tx / info->gNB->frame_parms.get_samples_per_slot(slot_tx, &info->gNB->frame_parms);
|
||||
int absslot_rx = absslot_tx - info->gNB->RU_list[0]->sl_ahead;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &gNB->rt_L1_profiling.start_L1_TX[rt_prof_idx]);
|
||||
phy_procedures_gNB_TX(info,
|
||||
frame_tx,
|
||||
slot_tx,
|
||||
1);
|
||||
clock_gettime(CLOCK_MONOTONIC, &gNB->rt_L1_profiling.return_L1_TX[rt_prof_idx]);
|
||||
LOG_D(NR_PHY, "%d.%d running tx_func\n", frame_tx, slot_tx);
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
module_id_t module_id = gNB->Mod_id;
|
||||
uint8_t CC_id = gNB->CC_id;
|
||||
NR_IF_Module_t *ifi = gNB->if_inst;
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
|
||||
if (get_softmodem_params()->reorder_thread_disable) {
|
||||
T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx));
|
||||
|
||||
if (slot_rx == 0) {
|
||||
reset_active_stats(gNB, frame_rx);
|
||||
reset_active_ulsch(gNB, frame_rx);
|
||||
}
|
||||
|
||||
start_meas(&gNB->slot_indication_stats);
|
||||
ifi->NR_slot_indication(module_id, CC_id, frame_tx, slot_tx);
|
||||
stop_meas(&gNB->slot_indication_stats);
|
||||
gNB->msgDataTx->timestamp_tx = info->timestamp_tx;
|
||||
info = gNB->msgDataTx;
|
||||
info->gNB = gNB;
|
||||
|
||||
// At this point, MAC scheduler just ran, including scheduling
|
||||
// PRACH/PUCCH/PUSCH, so trigger RX chain processing
|
||||
LOG_D(NR_PHY, "%s() trigger RX for %d.%d\n", __func__, frame_rx, slot_rx);
|
||||
notifiedFIFO_elt_t *res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->resp_L1, NULL);
|
||||
processingData_L1_t *syncMsg = NotifiedFifoData(res);
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->frame_rx = frame_rx;
|
||||
syncMsg->slot_rx = slot_rx;
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
res->key = slot_rx;
|
||||
pushNotifiedFIFO(&gNB->resp_L1, res);
|
||||
|
||||
int tx_slot_type = nr_slot_select(cfg, frame_tx, slot_tx);
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx) {
|
||||
start_meas(&info->gNB->phy_proc_tx);
|
||||
phy_procedures_gNB_TX(info, frame_tx, slot_tx, 1);
|
||||
const int rt_prof_idx = absslot_rx % RT_PROF_DEPTH;
|
||||
clock_gettime(CLOCK_MONOTONIC, &info->gNB->rt_L1_profiling.return_L1_TX[rt_prof_idx]);
|
||||
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
processingData_RU_t syncMsgRU;
|
||||
syncMsgRU.frame_tx = frame_tx;
|
||||
syncMsgRU.slot_tx = slot_tx;
|
||||
syncMsgRU.ru = gNB->RU_list[0];
|
||||
syncMsgRU.timestamp_tx = info->timestamp_tx;
|
||||
LOG_D(PHY,"gNB: %d.%d : calling RU TX function\n",syncMsgRU.frame_tx,syncMsgRU.slot_tx);
|
||||
ru_tx_func((void*)&syncMsgRU);
|
||||
LOG_D(PHY, "gNB: %d.%d : calling RU TX function\n", syncMsgRU.frame_tx, syncMsgRU.slot_tx);
|
||||
ru_tx_func((void *)&syncMsgRU);
|
||||
stop_meas(&info->gNB->phy_proc_tx);
|
||||
}
|
||||
/* this thread is done with the sched_info, decrease the reference counter */
|
||||
LOG_D(NR_PHY, "Calling deref_sched_response for id %d (tx_func) in %d.%d\n", info->sched_response_id, frame_tx, slot_tx);
|
||||
deref_sched_response(info->sched_response_id);
|
||||
stop_meas(&gNB->phy_proc_tx);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,27 +192,27 @@ void *L1_rx_thread(void *arg)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/* to be added for URLLC, requires MAC scheduling to be split from UL indication
|
||||
// Added for URLLC, requires MAC scheduling to be split from UL indication
|
||||
void *L1_tx_thread(void *arg) {
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)arg;
|
||||
|
||||
while (oai_exit == 0) {
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&gNB->L1_tx_out);
|
||||
if (res == NULL) // stopping condition, happens only when queue is freed
|
||||
break;
|
||||
processingData_L1tx_t *info = (processingData_L1tx_t *)NotifiedFifoData(res);
|
||||
tx_func(info);
|
||||
delNotifiedFIFO_elt(res);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
void rx_func(void *param)
|
||||
{
|
||||
processingData_L1_t *info = (processingData_L1_t *) param;
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
int frame_rx = info->frame_rx;
|
||||
int slot_rx = info->slot_rx;
|
||||
int frame_tx = info->frame_tx;
|
||||
int slot_tx = info->slot_tx;
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
int cumul_samples = gNB->frame_parms.get_samples_per_slot(0, &gNB->frame_parms);
|
||||
int i = 1;
|
||||
@@ -204,32 +234,14 @@ void rx_func(void *param)
|
||||
handle_nr_slot_ind(frame_rx, slot_rx);
|
||||
stop_meas(&nfapi_meas);
|
||||
|
||||
/*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus||
|
||||
gNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs ||
|
||||
gNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs ||
|
||||
gNB->UL_INFO.rach_ind.number_of_pdus ||
|
||||
gNB->UL_INFO.cqi_ind.number_of_cqis
|
||||
) {
|
||||
LOG_D(PHY, "UL_info[rx_ind:%05d:%d harqs:%05d:%d crcs:%05d:%d rach_pdus:%0d.%d:%d cqis:%d] RX:%04d%d TX:%04d%d \n",
|
||||
NFAPI_SFNSF2DEC(gNB->UL_INFO.rx_ind.sfn_sf), gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus,
|
||||
NFAPI_SFNSF2DEC(gNB->UL_INFO.harq_ind.sfn_sf), gNB->UL_INFO.harq_ind.harq_indication_body.number_of_harqs,
|
||||
NFAPI_SFNSF2DEC(gNB->UL_INFO.crc_ind.sfn_sf), gNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs,
|
||||
gNB->UL_INFO.rach_ind.sfn, gNB->UL_INFO.rach_ind.slot,gNB->UL_INFO.rach_ind.number_of_pdus,
|
||||
gNB->UL_INFO.cqi_ind.number_of_cqis,
|
||||
frame_rx, slot_rx,
|
||||
frame_tx, slot_tx);
|
||||
}*/
|
||||
}
|
||||
// ****************************************
|
||||
|
||||
T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx));
|
||||
|
||||
reset_active_stats(gNB, frame_tx);
|
||||
reset_active_ulsch(gNB, frame_tx);
|
||||
|
||||
// RX processing
|
||||
int rx_slot_type = nr_slot_select(cfg, frame_rx, slot_rx);
|
||||
if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) {
|
||||
LOG_D(NR_PHY, "%d.%d Starting RX processing\n", frame_rx, slot_rx);
|
||||
|
||||
// UE-specific RX processing for subframe n
|
||||
// TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT
|
||||
|
||||
@@ -252,98 +264,30 @@ void rx_func(void *param)
|
||||
}
|
||||
}
|
||||
phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx);
|
||||
}
|
||||
|
||||
stop_meas( &softmodem_stats_rxtx_sf );
|
||||
LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
|
||||
clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.return_L1_RX[rt_prof_idx]);
|
||||
// Call the scheduler
|
||||
start_meas(&gNB->ul_indication_stats);
|
||||
gNB->UL_INFO.frame = frame_rx;
|
||||
gNB->UL_INFO.slot = slot_rx;
|
||||
gNB->UL_INFO.module_id = gNB->Mod_id;
|
||||
gNB->UL_INFO.CC_id = gNB->CC_id;
|
||||
gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
|
||||
stop_meas(&gNB->ul_indication_stats);
|
||||
|
||||
// Call the scheduler
|
||||
start_meas(&gNB->ul_indication_stats);
|
||||
// pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
gNB->UL_INFO.frame = frame_rx;
|
||||
gNB->UL_INFO.slot = slot_rx;
|
||||
gNB->UL_INFO.module_id = gNB->Mod_id;
|
||||
gNB->UL_INFO.CC_id = gNB->CC_id;
|
||||
gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
|
||||
// pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
stop_meas(&gNB->ul_indication_stats);
|
||||
|
||||
int tx_slot_type = nr_slot_select(cfg,frame_tx,slot_tx);
|
||||
if ((tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) && NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
notifiedFIFO_elt_t *res;
|
||||
processingData_L1tx_t *syncMsg;
|
||||
// Its a FIFO so it maitains the order in which the MAC fills the messages
|
||||
// so no need for checking for right slot
|
||||
if (get_softmodem_params()->reorder_thread_disable) {
|
||||
// call the TX function directly from this thread
|
||||
syncMsg = gNB->msgDataTx;
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
tx_func(syncMsg);
|
||||
} else {
|
||||
res = pullTpool(&gNB->L1_tx_filled, &gNB->threadPool);
|
||||
if (res == NULL)
|
||||
return; // Tpool has been stopped
|
||||
syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
res->key = slot_tx;
|
||||
pushTpool(&gNB->threadPool, res);
|
||||
}
|
||||
} else if (get_softmodem_params()->continuous_tx) {
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&gNB->L1_tx_free);
|
||||
if (res == NULL)
|
||||
return; // Tpool has been stopped
|
||||
processingData_L1tx_t *syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
|
||||
notifiedFIFO_elt_t *res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->L1_rx_out, NULL);
|
||||
processingData_L1_t *syncMsg = NotifiedFifoData(res);
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
syncMsg->frame = frame_tx;
|
||||
syncMsg->slot = slot_tx;
|
||||
res->key = slot_tx;
|
||||
pushNotifiedFIFO(&gNB->L1_tx_out, res);
|
||||
syncMsg->frame_rx = frame_rx;
|
||||
syncMsg->slot_rx = slot_rx;
|
||||
res->key = slot_rx;
|
||||
LOG_D(NR_PHY, "Signaling completion for %d.%d (mod_slot %d) on L1_rx_out\n", frame_rx, slot_rx, slot_rx % RU_RX_SLOT_DEPTH);
|
||||
pushNotifiedFIFO(&gNB->L1_rx_out, res);
|
||||
}
|
||||
|
||||
#if 0
|
||||
LOG_D(PHY, "rxtx:%lld nfapi:%lld phy:%lld tx:%lld rx:%lld prach:%lld ofdm:%lld ",
|
||||
softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now,
|
||||
TICK_TO_US(gNB->phy_proc),
|
||||
TICK_TO_US(gNB->phy_proc_tx),
|
||||
TICK_TO_US(gNB->phy_proc_rx),
|
||||
TICK_TO_US(gNB->rx_prach),
|
||||
TICK_TO_US(gNB->ofdm_mod_stats),
|
||||
softmodem_stats_rxtx_sf.diff_now, nfapi_meas.diff_now);
|
||||
LOG_D(PHY,
|
||||
"dlsch[enc:%lld mod:%lld scr:%lld rm:%lld t:%lld i:%lld] rx_dft:%lld ",
|
||||
TICK_TO_US(gNB->dlsch_encoding_stats),
|
||||
TICK_TO_US(gNB->dlsch_modulation_stats),
|
||||
TICK_TO_US(gNB->dlsch_scrambling_stats),
|
||||
TICK_TO_US(gNB->dlsch_rate_matching_stats),
|
||||
TICK_TO_US(gNB->dlsch_turbo_encoding_stats),
|
||||
TICK_TO_US(gNB->dlsch_interleaving_stats),
|
||||
TICK_TO_US(gNB->rx_dft_stats));
|
||||
LOG_D(PHY," ulsch[ch:%lld freq:%lld dec:%lld demod:%lld ru:%lld ",
|
||||
TICK_TO_US(gNB->ulsch_channel_estimation_stats),
|
||||
TICK_TO_US(gNB->ulsch_freq_offset_estimation_stats),
|
||||
TICK_TO_US(gNB->ulsch_decoding_stats),
|
||||
TICK_TO_US(gNB->ulsch_demodulation_stats),
|
||||
TICK_TO_US(gNB->ulsch_rate_unmatching_stats));
|
||||
LOG_D(PHY, "td:%lld dei:%lld dem:%lld llr:%lld tci:%lld ",
|
||||
TICK_TO_US(gNB->ulsch_turbo_decoding_stats),
|
||||
TICK_TO_US(gNB->ulsch_deinterleaving_stats),
|
||||
TICK_TO_US(gNB->ulsch_demultiplexing_stats),
|
||||
TICK_TO_US(gNB->ulsch_llr_stats),
|
||||
TICK_TO_US(gNB->ulsch_tc_init_stats));
|
||||
LOG_D(PHY, "tca:%lld tcb:%lld tcg:%lld tce:%lld l1:%lld l2:%lld]\n\n",
|
||||
TICK_TO_US(gNB->ulsch_tc_alpha_stats),
|
||||
TICK_TO_US(gNB->ulsch_tc_beta_stats),
|
||||
TICK_TO_US(gNB->ulsch_tc_gamma_stats),
|
||||
TICK_TO_US(gNB->ulsch_tc_ext_stats),
|
||||
TICK_TO_US(gNB->ulsch_tc_intl1_stats),
|
||||
TICK_TO_US(gNB->ulsch_tc_intl2_stats)
|
||||
);
|
||||
#endif
|
||||
stop_meas(&softmodem_stats_rxtx_sf);
|
||||
clock_gettime(CLOCK_MONOTONIC, &info->gNB->rt_L1_profiling.return_L1_RX[rt_prof_idx]);
|
||||
}
|
||||
|
||||
static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size_t outputlen) {
|
||||
const char *begin = output;
|
||||
const char *end = output + outputlen;
|
||||
@@ -356,8 +300,8 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size
|
||||
output += print_meas_log(&gNB->dlsch_precoding_stats, "DLSCH precoding", NULL, NULL, output,end-output);
|
||||
output += print_meas_log(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->ul_indication_stats, "UL Indication", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->slot_indication_stats, "Slot Indication", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->ulsch_decoding_stats, "PUSCH decoding", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->schedule_response_stats, "Schedule Response", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->rx_prach, "PRACH RX", NULL, NULL, output, end - output);
|
||||
if (ru->feprx)
|
||||
@@ -399,8 +343,8 @@ void *nrL1_stats_thread(void *param) {
|
||||
reset_meas(&gNB->dlsch_encoding_stats);
|
||||
reset_meas(&gNB->phy_proc_rx);
|
||||
reset_meas(&gNB->ul_indication_stats);
|
||||
reset_meas(&gNB->slot_indication_stats);
|
||||
reset_meas(&gNB->rx_pusch_stats);
|
||||
reset_meas(&gNB->ulsch_decoding_stats);
|
||||
reset_meas(&gNB->schedule_response_stats);
|
||||
reset_meas(&gNB->dlsch_scrambling_stats);
|
||||
reset_meas(&gNB->dlsch_modulation_stats);
|
||||
@@ -421,60 +365,6 @@ void *nrL1_stats_thread(void *param) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// This thread reads the finished L1 tx jobs from threaPool
|
||||
// and pushes RU tx thread in the right order. It works only
|
||||
// two parallel L1 tx threads.
|
||||
void *tx_reorder_thread(void* param) {
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
|
||||
|
||||
notifiedFIFO_elt_t *resL1Reserve = pullNotifiedFIFO(&gNB->L1_tx_out);
|
||||
AssertFatal(resL1Reserve != NULL, "pullTpool() did not return start message in %s\n", __func__);
|
||||
int next_tx_slot=((processingData_L1tx_t *)NotifiedFifoData(resL1Reserve))->slot;
|
||||
|
||||
LOG_I(PHY,"tx_reorder_thread started\n");
|
||||
|
||||
while (!oai_exit) {
|
||||
notifiedFIFO_elt_t *resL1;
|
||||
if (resL1Reserve) {
|
||||
resL1=resL1Reserve;
|
||||
if (((processingData_L1tx_t *)NotifiedFifoData(resL1))->slot != next_tx_slot) {
|
||||
LOG_E(PHY,"order mistake\n");
|
||||
resL1Reserve = NULL;
|
||||
resL1 = pullNotifiedFIFO(&gNB->L1_tx_out);
|
||||
}
|
||||
} else {
|
||||
resL1 = pullNotifiedFIFO(&gNB->L1_tx_out);
|
||||
if (resL1 != NULL && ((processingData_L1tx_t *)NotifiedFifoData(resL1))->slot != next_tx_slot) {
|
||||
if (resL1Reserve)
|
||||
LOG_E(PHY,"error, have a stored packet, then a second one\n");
|
||||
resL1Reserve = resL1;
|
||||
resL1 = pullNotifiedFIFO(&gNB->L1_tx_out);
|
||||
if (((processingData_L1tx_t *)NotifiedFifoData(resL1))->slot != next_tx_slot)
|
||||
LOG_E(PHY,"error, pull two msg, none is good\n");
|
||||
}
|
||||
}
|
||||
if (resL1 == NULL)
|
||||
break; // Tpool has been stopped
|
||||
processingData_L1tx_t *syncMsgL1= (processingData_L1tx_t *)NotifiedFifoData(resL1);
|
||||
processingData_RU_t syncMsgRU;
|
||||
syncMsgRU.frame_tx = syncMsgL1->frame;
|
||||
syncMsgRU.slot_tx = syncMsgL1->slot;
|
||||
syncMsgRU.timestamp_tx = syncMsgL1->timestamp_tx;
|
||||
syncMsgRU.ru = gNB->RU_list[0];
|
||||
if (get_softmodem_params()->continuous_tx) {
|
||||
int slots_per_frame = gNB->frame_parms.slots_per_frame;
|
||||
next_tx_slot = (syncMsgRU.slot_tx + 1) % slots_per_frame;
|
||||
} else
|
||||
next_tx_slot = get_next_downlink_slot(gNB, &gNB->gNB_config, syncMsgRU.frame_tx, syncMsgRU.slot_tx);
|
||||
pushNotifiedFIFO(&gNB->L1_tx_free, resL1);
|
||||
if (resL1==resL1Reserve)
|
||||
resL1Reserve=NULL;
|
||||
LOG_D(PHY,"gNB: %d.%d : calling RU TX function\n",syncMsgL1->frame,syncMsgL1->slot);
|
||||
ru_tx_func((void*)&syncMsgRU);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void init_gNB_Tpool(int inst) {
|
||||
PHY_VARS_gNB *gNB;
|
||||
gNB = RC.gNB[inst];
|
||||
@@ -487,47 +377,26 @@ void init_gNB_Tpool(int inst) {
|
||||
initNotifiedFIFO(&gNB->respPuschSymb);
|
||||
initNotifiedFIFO(&gNB->respDecode);
|
||||
|
||||
// L1 RX result FIFO
|
||||
// L1 RX result FIFO
|
||||
initNotifiedFIFO(&gNB->resp_L1);
|
||||
if (!get_softmodem_params()->reorder_thread_disable) {
|
||||
notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->resp_L1, rx_func);
|
||||
pushNotifiedFIFO(&gNB->resp_L1, msg); // to unblock the process in the beginning
|
||||
}
|
||||
// L1 TX result FIFO
|
||||
initNotifiedFIFO(&gNB->L1_tx_free);
|
||||
initNotifiedFIFO(&gNB->L1_tx_filled);
|
||||
initNotifiedFIFO(&gNB->L1_tx_out);
|
||||
|
||||
if (get_softmodem_params()->reorder_thread_disable) {
|
||||
// create the RX thread responsible for triggering RX processing and then TX processing if a single thread is used
|
||||
threadCreate(&gNB->L1_rx_thread, L1_rx_thread, (void *)gNB, "L1_rx_thread",
|
||||
gNB->L1_rx_thread_core, OAI_PRIORITY_RT_MAX);
|
||||
// if separate threads are used for RX and TX, create the TX thread
|
||||
// threadCreate(&gNB->L1_tx_thread, L1_tx_thread, (void *)gNB, "L1_tx_thread",
|
||||
// gNB->L1_tx_thread_core, OAI_PRIORITY_RT_MAX);
|
||||
initNotifiedFIFO(&gNB->L1_rx_out);
|
||||
|
||||
notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, tx_func);
|
||||
processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
|
||||
memset(msgDataTx, 0, sizeof(processingData_L1tx_t));
|
||||
init_DLSCH_struct(gNB, msgDataTx);
|
||||
memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
|
||||
// this will be removed when the msgDataTx is not necessary anymore
|
||||
gNB->msgDataTx = msgDataTx;
|
||||
} else {
|
||||
// we create 2 threads for L1 tx processing
|
||||
for (int i=0; i < 2; i++) {
|
||||
notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, tx_func);
|
||||
processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
|
||||
memset(msgDataTx, 0, sizeof(processingData_L1tx_t));
|
||||
init_DLSCH_struct(gNB, msgDataTx);
|
||||
memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
|
||||
pushNotifiedFIFO(&gNB->L1_tx_free, msgL1Tx); // to unblock the process in the beginning
|
||||
}
|
||||
|
||||
LOG_I(PHY,"Creating thread for TX reordering and dispatching to RU\n");
|
||||
threadCreate(&proc->pthread_tx_reorder, tx_reorder_thread, (void *)gNB, "thread_tx_reorder",
|
||||
gNB->RU_list[0] ? gNB->RU_list[0]->tpcores[1] : -1, OAI_PRIORITY_RT_MAX);
|
||||
}
|
||||
// create the RX thread responsible for RX processing start event (resp_L1 msg queue), then launch rx_func()
|
||||
threadCreate(&gNB->L1_rx_thread, L1_rx_thread, (void *)gNB, "L1_rx_thread", gNB->L1_rx_thread_core, OAI_PRIORITY_RT_MAX);
|
||||
// create the TX thread responsible for TX processing start event (L1_tx_out msg queue), then launch tx_func()
|
||||
threadCreate(&gNB->L1_tx_thread, L1_tx_thread, (void *)gNB, "L1_tx_thread", gNB->L1_tx_thread_core, OAI_PRIORITY_RT_MAX);
|
||||
|
||||
notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, tx_func);
|
||||
processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
|
||||
memset(msgDataTx, 0, sizeof(processingData_L1tx_t));
|
||||
init_DLSCH_struct(gNB, msgDataTx);
|
||||
memset(msgDataTx->ssb, 0, 64 * sizeof(NR_gNB_SSB_t));
|
||||
// this will be removed when the msgDataTx is not necessary anymore
|
||||
gNB->msgDataTx = msgDataTx;
|
||||
|
||||
if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS_BIT) && (NFAPI_MODE!=NFAPI_MODE_VNF))
|
||||
threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW);
|
||||
@@ -543,25 +412,11 @@ void term_gNB_Tpool(int inst) {
|
||||
abortNotifiedFIFO(&gNB->L1_tx_free);
|
||||
abortNotifiedFIFO(&gNB->L1_tx_filled);
|
||||
abortNotifiedFIFO(&gNB->L1_tx_out);
|
||||
abortNotifiedFIFO(&gNB->L1_rx_out);
|
||||
|
||||
gNB_L1_proc_t *proc = &gNB->proc;
|
||||
if (!get_softmodem_params()->emulate_l1)
|
||||
pthread_join(proc->L1_stats_thread, NULL);
|
||||
if (!get_softmodem_params()->reorder_thread_disable)
|
||||
pthread_join(proc->pthread_tx_reorder, NULL);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Terminate gNB TX and RX threads.
|
||||
*/
|
||||
void kill_gNB_proc(int inst) {
|
||||
PHY_VARS_gNB *gNB;
|
||||
|
||||
gNB=RC.gNB[inst];
|
||||
|
||||
LOG_I(PHY, "Destroying UL_INFO mutex\n");
|
||||
pthread_mutex_destroy(&gNB->UL_INFO_mutex);
|
||||
|
||||
}
|
||||
|
||||
void reset_opp_meas(void) {
|
||||
@@ -601,7 +456,6 @@ void init_eNB_afterRU(void) {
|
||||
|
||||
gNB = RC.gNB[inst];
|
||||
gNB->ldpc_offload_flag = get_softmodem_params()->ldpc_offload_flag;
|
||||
gNB->reorder_thread_disable = get_softmodem_params()->reorder_thread_disable;
|
||||
|
||||
phy_init_nr_gNB(gNB);
|
||||
|
||||
@@ -692,6 +546,5 @@ void stop_gNB(int nb_inst) {
|
||||
for (int inst=0; inst<nb_inst; inst++) {
|
||||
LOG_I(PHY,"Killing gNB %d processing threads\n",inst);
|
||||
term_gNB_Tpool(inst);
|
||||
kill_gNB_proc(inst);
|
||||
}
|
||||
}
|
||||
|
||||
+101
-44
@@ -283,7 +283,7 @@ void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
for (int aid=0;aid<ru->nb_tx;aid++) buffs[aid] = (void*)&ru->common.txdata[aid][offset];
|
||||
struct timespec txmeas;
|
||||
clock_gettime(CLOCK_MONOTONIC, &txmeas);
|
||||
LOG_D(PHY,"IF5 TX %d.%d, TS %llu, buffs[0] %p, buffs[1] %p ener0 %f dB, tx start %d\n",frame,slot,(unsigned long long)timestamp,buffs[0],buffs[1],
|
||||
LOG_D(NR_PHY,"IF5 TX %d.%d, TS %llu, buffs[0] %p, buffs[1] %p ener0 %f dB, tx start %d\n",frame,slot,(unsigned long long)timestamp,buffs[0],buffs[1],
|
||||
10*log10((double)signal_energy(buffs[0],ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms))),(int)txmeas.tv_nsec);
|
||||
ru->ifdevice.trx_write_func2(&ru->ifdevice,
|
||||
timestamp,
|
||||
@@ -624,7 +624,8 @@ void *emulatedRF_thread(void *param) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
{
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
openair0_config_t *cfg = &ru->openair0_cfg;
|
||||
@@ -662,13 +663,17 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
|
||||
//AssertFatal(rxs == fp->samples_per_subframe,
|
||||
//"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs);
|
||||
if (rxs != samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",samples_per_slot,rxs);
|
||||
if (rxs != samples_per_slot)
|
||||
LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n", samples_per_slot, rxs);
|
||||
|
||||
if (proc->first_rx != 1) {
|
||||
samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp);
|
||||
|
||||
if (proc->timestamp_rx - old_ts != samples_per_slot_prev) {
|
||||
LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot_prev,ru->ts_offset);
|
||||
LOG_D(PHY,
|
||||
"rx_rf: rfdevice timing drift of %" PRId64 " samples (ts_off %" PRId64 ")\n",
|
||||
proc->timestamp_rx - old_ts - samples_per_slot_prev,
|
||||
ru->ts_offset);
|
||||
ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot_prev);
|
||||
proc->timestamp_rx = ts-ru->ts_offset;
|
||||
}
|
||||
@@ -705,8 +710,14 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
}
|
||||
|
||||
if (proc->frame_rx != *frame) {
|
||||
LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,
|
||||
*frame,proc->tti_rx,*slot);
|
||||
LOG_E(PHY,
|
||||
"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d, proc->tti_rx %d, "
|
||||
"slot %d)\n",
|
||||
(long long unsigned int)proc->timestamp_rx,
|
||||
proc->frame_rx,
|
||||
*frame,
|
||||
proc->tti_rx,
|
||||
*slot);
|
||||
exit_fun("Exiting");
|
||||
}
|
||||
} else {
|
||||
@@ -1169,6 +1180,7 @@ void *ru_thread( void *param ) {
|
||||
int initial_wait=0;
|
||||
int opp_enabled0 = opp_enabled;
|
||||
|
||||
bool rx_tti_busy[RU_RX_SLOT_DEPTH] = {false};
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
// set default return value
|
||||
ru_thread_status = 0;
|
||||
@@ -1204,6 +1216,18 @@ void *ru_thread( void *param ) {
|
||||
malloc_IF4p5_buffer(ru);
|
||||
}
|
||||
|
||||
int cpu = sched_getcpu();
|
||||
if (ru->ru_thread_core > -1 && cpu != ru->ru_thread_core) {
|
||||
/* we start the ru_thread using threadCreate(), which already sets CPU
|
||||
* affinity; let's force it here again as per feature request #732 */
|
||||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(ru->ru_thread_core, &cpuset);
|
||||
int ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
|
||||
AssertFatal(ret == 0, "Error in pthread_getaffinity_np(): ret: %d, errno: %d", ret, errno);
|
||||
LOG_I(PHY, "RU %d: manually set CPU affinity to CPU %d\n", ru->idx, ru->ru_thread_core);
|
||||
}
|
||||
|
||||
LOG_I(PHY,"Starting IF interface for RU %d, nb_rx %d\n",ru->idx,ru->nb_rx);
|
||||
AssertFatal(ru->nr_start_if(ru,NULL) == 0, "Could not start the IF device\n");
|
||||
|
||||
@@ -1233,9 +1257,6 @@ void *ru_thread( void *param ) {
|
||||
pthread_mutex_unlock(&RC.ru_mutex);
|
||||
wait_sync("ru_thread");
|
||||
|
||||
processingData_L1_t *syncMsg;
|
||||
notifiedFIFO_elt_t *res;
|
||||
|
||||
if(!emulate_rf) {
|
||||
// Start RF device if any
|
||||
if (ru->start_rf) {
|
||||
@@ -1299,14 +1320,13 @@ void *ru_thread( void *param ) {
|
||||
if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot);
|
||||
else AssertFatal(1==0, "No fronthaul interface at south port");
|
||||
|
||||
|
||||
if (initial_wait == 1 && proc->frame_rx < 300 && ru->fh_south_in == rx_rf) {
|
||||
if (proc->frame_rx>0 && ((proc->frame_rx % 100) == 0) && proc->tti_rx==0) {
|
||||
LOG_I(PHY,"delay processing to let RX stream settle, frame %d (trials %d)\n",proc->frame_rx,ru->rx_fhaul.trials);
|
||||
print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);
|
||||
reset_meas(&ru->rx_fhaul);
|
||||
}
|
||||
continue;
|
||||
if (initial_wait == 1 && proc->frame_rx < 300) {
|
||||
if (proc->frame_rx > 0 && ((proc->frame_rx % 100) == 0) && proc->tti_rx == 0) {
|
||||
LOG_D(PHY, "delay processing to let RX stream settle, frame %d (trials %d)\n", proc->frame_rx, ru->rx_fhaul.trials);
|
||||
print_meas(&ru->rx_fhaul, "rx_fhaul", NULL, NULL);
|
||||
reset_meas(&ru->rx_fhaul);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (proc->frame_rx>=300) {
|
||||
initial_wait=0;
|
||||
@@ -1314,15 +1334,14 @@ void *ru_thread( void *param ) {
|
||||
}
|
||||
if (initial_wait == 0 && ru->rx_fhaul.trials > 1000) {
|
||||
reset_meas(&ru->rx_fhaul);
|
||||
/*if (ru->if_south == REMOTE_IF5) reset_meas(&ru->ifdevice.tx_fhaul);
|
||||
else*/ reset_meas(&ru->tx_fhaul);
|
||||
reset_meas(&ru->tx_fhaul);
|
||||
}
|
||||
proc->timestamp_tx = proc->timestamp_rx;
|
||||
int sl=proc->tti_tx;
|
||||
for (int slidx=0;slidx<ru->sl_ahead;slidx++)
|
||||
proc->timestamp_tx += fp->get_samples_per_slot((sl+slidx)%fp->slots_per_frame,fp);
|
||||
proc->frame_tx = (proc->tti_rx > (fp->slots_per_frame-1-(ru->sl_ahead))) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
|
||||
proc->tti_tx = (proc->tti_rx + ru->sl_ahead)%fp->slots_per_frame;
|
||||
proc->frame_tx = (proc->tti_rx > (fp->slots_per_frame - 1 - (ru->sl_ahead))) ? (proc->frame_rx + 1) & 1023 : proc->frame_rx;
|
||||
proc->tti_tx = (proc->tti_rx + ru->sl_ahead) % fp->slots_per_frame;
|
||||
int absslot_rx = proc->timestamp_rx/fp->get_samples_per_slot(proc->tti_rx,fp);
|
||||
int rt_prof_idx = absslot_rx % RT_PROF_DEPTH;
|
||||
clock_gettime(CLOCK_MONOTONIC,&ru->rt_ru_profiling.return_RU_south_in[rt_prof_idx]);
|
||||
@@ -1333,14 +1352,62 @@ void *ru_thread( void *param ) {
|
||||
RC.gNB[0]->proc.frame_rx,RC.gNB[0]->proc.slot_rx,
|
||||
RC.gNB[0]->proc.frame_tx);
|
||||
|
||||
if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023;
|
||||
if (ru->idx != 0)
|
||||
proc->frame_tx = (proc->frame_tx + proc->frame_offset) & 1023;
|
||||
|
||||
LOG_D(NR_PHY, "In %d.%d: Checking L1 status\n", proc->frame_rx, proc->tti_rx);
|
||||
for (int n = 0; n < RU_RX_SLOT_DEPTH; n++)
|
||||
LOG_D(NR_PHY, "slot n %d => %d\n", n, rx_tti_busy[n]);
|
||||
// handle potential race by blocking if rxdataF is being used by L1
|
||||
// collect all pending msg in L1 return fifo to not down the memory is available (rx_tti_busy[slot] boolean array)
|
||||
notifiedFIFO_elt_t *res = pollNotifiedFIFO(&gNB->L1_rx_out);
|
||||
LOG_D(NR_PHY, "%d.%d Polling L1_rx_out %p\n", proc->frame_rx, proc->tti_rx, res);
|
||||
while (res) {
|
||||
processingData_L1_t *info = (processingData_L1_t *)NotifiedFifoData(res);
|
||||
LOG_D(NR_PHY,
|
||||
"%d.%d res %d.%d completed, clearing %d\n",
|
||||
proc->frame_rx,
|
||||
proc->tti_rx,
|
||||
info->frame_rx,
|
||||
info->slot_rx,
|
||||
info->slot_rx % RU_RX_SLOT_DEPTH);
|
||||
|
||||
rx_tti_busy[info->slot_rx % RU_RX_SLOT_DEPTH] = false;
|
||||
res = pollNotifiedFIFO(&gNB->L1_rx_out);
|
||||
}
|
||||
LOG_D(NR_PHY, "%d.%d Done polling\n", proc->frame_rx, proc->tti_rx);
|
||||
// do RX front-end processing (frequency-shift, dft) if needed
|
||||
int slot_type = nr_slot_select(cfg,proc->frame_rx,proc->tti_rx);
|
||||
|
||||
int slot_type = nr_slot_select(cfg, proc->frame_rx, proc->tti_rx);
|
||||
if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
|
||||
if (ru->feprx) {
|
||||
if (rx_tti_busy[proc->tti_rx % RU_RX_SLOT_DEPTH]) {
|
||||
bool not_done = true;
|
||||
LOG_D(NR_PHY, "%d.%d Waiting to access RX slot %d\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH);
|
||||
// now we block and wait our slot memory zone is freed from previous slot processing
|
||||
// as we can get other slots ending, we loop on the queue
|
||||
while (not_done) {
|
||||
res = pullNotifiedFIFO(&gNB->L1_rx_out);
|
||||
if (!res)
|
||||
break;
|
||||
processingData_L1_t *info = (processingData_L1_t *)NotifiedFifoData(res);
|
||||
LOG_D(NR_PHY,
|
||||
"%d.%d Got access to RX slot %d.%d (%d)\n",
|
||||
proc->frame_rx,
|
||||
proc->tti_rx,
|
||||
info->frame_rx,
|
||||
info->slot_rx,
|
||||
proc->tti_rx % RU_RX_SLOT_DEPTH);
|
||||
rx_tti_busy[info->slot_rx % RU_RX_SLOT_DEPTH] = false;
|
||||
if ((info->slot_rx % RU_RX_SLOT_DEPTH) == (proc->tti_rx % RU_RX_SLOT_DEPTH))
|
||||
not_done = false;
|
||||
}
|
||||
if (!res)
|
||||
break;
|
||||
}
|
||||
ru->feprx(ru,proc->tti_rx);
|
||||
// set the tti that was generated to busy
|
||||
LOG_D(NR_PHY, "Setting %d.%d (%d) to busy\n", proc->frame_rx, proc->tti_rx, proc->tti_rx % RU_RX_SLOT_DEPTH);
|
||||
rx_tti_busy[proc->tti_rx % RU_RX_SLOT_DEPTH] = true;
|
||||
clock_gettime(CLOCK_MONOTONIC,&ru->rt_ru_profiling.return_RU_feprx[rt_prof_idx]);
|
||||
//LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1);
|
||||
LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx);
|
||||
@@ -1383,26 +1450,16 @@ void *ru_thread( void *param ) {
|
||||
}
|
||||
} // end if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
|
||||
|
||||
// At this point, all information for subframe has been received on FH interface
|
||||
if (!get_softmodem_params()->reorder_thread_disable) {
|
||||
res = pullTpool(&gNB->resp_L1, &gNB->threadPool);
|
||||
if (res == NULL)
|
||||
break; // Tpool has been stopped
|
||||
} else {
|
||||
res=newNotifiedFIFO_elt(sizeof(processingData_L1_t),0, &gNB->resp_L1,NULL);
|
||||
}
|
||||
syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
|
||||
syncMsg->gNB = gNB;
|
||||
syncMsg->frame_rx = proc->frame_rx;
|
||||
syncMsg->slot_rx = proc->tti_rx;
|
||||
syncMsg->frame_tx = proc->frame_tx;
|
||||
syncMsg->slot_tx = proc->tti_tx;
|
||||
syncMsg->timestamp_tx = proc->timestamp_tx;
|
||||
res->key = proc->tti_rx;
|
||||
if (!get_softmodem_params()->reorder_thread_disable)
|
||||
pushTpool(&gNB->threadPool, res);
|
||||
else
|
||||
pushNotifiedFIFO(&gNB->resp_L1, res);
|
||||
notifiedFIFO_elt_t *resTx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, NULL);
|
||||
processingData_L1tx_t *syncMsgTx = NotifiedFifoData(resTx);
|
||||
syncMsgTx->gNB = gNB;
|
||||
syncMsgTx->frame = proc->frame_tx;
|
||||
syncMsgTx->slot = proc->tti_tx;
|
||||
syncMsgTx->frame_rx = proc->frame_rx;
|
||||
syncMsgTx->slot_rx = proc->tti_rx;
|
||||
syncMsgTx->timestamp_tx = proc->timestamp_tx;
|
||||
resTx->key = proc->tti_tx;
|
||||
pushNotifiedFIFO(&gNB->L1_tx_out, resTx);
|
||||
}
|
||||
|
||||
printf( "Exiting ru_thread \n");
|
||||
|
||||
@@ -299,7 +299,6 @@ static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cf
|
||||
|
||||
RCconfig_verify(cfg, node_type);
|
||||
|
||||
RCconfig_NR_L1();
|
||||
RCconfig_nr_prs();
|
||||
|
||||
if (RC.nb_nr_macrlc_inst > 0)
|
||||
@@ -682,11 +681,13 @@ int main( int argc, char **argv ) {
|
||||
#endif
|
||||
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
|
||||
|
||||
if (RC.nb_nr_L1_inst > 0)
|
||||
RCconfig_NR_L1();
|
||||
|
||||
// don't create if node doesn't connect to RRC/S1/GTP
|
||||
const ngran_node_t node_type = get_node_type();
|
||||
|
||||
if (RC.nb_nr_L1_inst > 0)
|
||||
RCconfig_NR_L1();
|
||||
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
int ret = create_gNB_tasks(node_type, uniqCfg);
|
||||
AssertFatal(ret == 0, "cannot create ITTI tasks\n");
|
||||
|
||||
@@ -47,7 +47,6 @@ extern char *uecap_file;
|
||||
// In nr-gnb.c
|
||||
extern void init_gNB(int single_thread_flag,int wait_for_sync);
|
||||
extern void stop_gNB(int);
|
||||
extern void kill_gNB_proc(int inst);
|
||||
|
||||
// In nr-ru.c
|
||||
extern void init_NR_RU(configmodule_interface_t *cfg, char *);
|
||||
|
||||
+3
-1
@@ -343,7 +343,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
|
||||
|
||||
if (is_nr_UL_slot(mac->tdd_UL_DL_ConfigurationCommon, ul_info.slot, mac->frame_type)) {
|
||||
LOG_D(NR_MAC, "Slot %d. calling nr_ue_ul_ind()\n", ul_info.slot);
|
||||
nr_ue_ul_scheduler(&ul_info);
|
||||
nr_ue_ul_scheduler(mac, &ul_info);
|
||||
}
|
||||
process_queued_nr_nfapi_msgs(mac, sfn_slot);
|
||||
}
|
||||
@@ -987,6 +987,8 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf
|
||||
init_nsa_message(rrc_inst, reconfig_file, rbconfig_file);
|
||||
nr_rlc_activate_srb0(mac_inst->crnti, NULL, send_srb0_rrc);
|
||||
}
|
||||
//TODO: Move this call to RRC
|
||||
start_sidelink((&rrc_inst[i])->ue_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ extern "C"
|
||||
example: -1,3 launches two working threads one floating, the second set on core 3\n\
|
||||
default 8 floating threads\n\
|
||||
use N for no pool (runs in calling thread) recommended with rfsim.\n"
|
||||
#define CONFIG_HLP_REORDER "Disable reorder thread\n"
|
||||
#define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n"
|
||||
#define CONFIG_HLP_CALUER "set UE RX calibration\n"
|
||||
#define CONFIG_HLP_CALUERM ""
|
||||
@@ -106,11 +105,9 @@ extern "C"
|
||||
#define CONFIG_L1_EMULATOR "Run in L1 emulated mode (disable PHY layer)\n"
|
||||
#define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n"
|
||||
#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence"
|
||||
#define CONFIG_HLP_SYNC_REF "Sync Reference in Sidelink\n"
|
||||
#define CONFIG_HLP_NID1 "Set NID1 value in Sidelink\n"
|
||||
#define CONFIG_HLP_NID2 "Set NID2 value in Sidelink\n"
|
||||
#define CONFIG_HLP_NOITTI "Do not start itti threads, call queue processing in place, inside the caller thread"
|
||||
#define CONFIG_HLP_LDPC_OFFLOAD "Enable LDPC offload to AMD Xilinx T2 telco card\n"
|
||||
#define CONFIG_HLP_SYNC_REF "UE acts a Sync Reference in Sidelink. 0-none 1-GNB 2-GNSS 4-localtiming\n"
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters common to eNodeB and UE */
|
||||
@@ -143,11 +140,8 @@ extern "C"
|
||||
#define EMULATE_L1 softmodem_params.emulate_l1
|
||||
#define CONTINUOUS_TX softmodem_params.continuous_tx
|
||||
#define SYNC_REF softmodem_params.sync_ref
|
||||
#define NID1 softmodem_params.nid1
|
||||
#define NID2 softmodem_params.nid2
|
||||
#define LDPC_OFFLOAD_FLAG softmodem_params.ldpc_offload_flag
|
||||
|
||||
#define REORDER_THREAD_DISABLE softmodem_params.reorder_thread_disable
|
||||
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
|
||||
|
||||
extern int usrp_tx_thread;
|
||||
@@ -155,7 +149,6 @@ extern int usrp_tx_thread;
|
||||
#define CMDLINE_PARAMS_DESC { \
|
||||
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, .strptr=&RF_CONFIG_FILE, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{"thread-pool", CONFIG_HLP_TPOOL, 0, .strptr=&TP_CONFIG, .defstrval="-1,-1,-1,-1,-1,-1,-1,-1", TYPE_STRING, 0}, \
|
||||
{"reorder-thread-disable",CONFIG_HLP_REORDER, PARAMFLAG_BOOL, .iptr=&REORDER_THREAD_DISABLE, .defintval=0, TYPE_INT, 0}, \
|
||||
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, .iptr=&PHY_TEST, .defintval=0, TYPE_INT, 0}, \
|
||||
{"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, .iptr=&DO_RA, .defintval=0, TYPE_INT, 0}, \
|
||||
{"sa", CONFIG_HLP_SA, PARAMFLAG_BOOL, .iptr=&SA, .defintval=0, TYPE_INT, 0}, \
|
||||
@@ -191,10 +184,9 @@ extern int usrp_tx_thread;
|
||||
{"emulate-l1", CONFIG_L1_EMULATOR, PARAMFLAG_BOOL, .iptr=&EMULATE_L1, .defintval=0, TYPE_INT, 0}, \
|
||||
{"continuous-tx", CONFIG_HLP_CONTINUOUS_TX, PARAMFLAG_BOOL, .iptr=&CONTINUOUS_TX, .defintval=0, TYPE_INT, 0}, \
|
||||
{"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \
|
||||
{"nid1", CONFIG_HLP_NID1, 0, .iptr=&NID1, .defintval=10, TYPE_INT, 0}, \
|
||||
{"nid2", CONFIG_HLP_NID2, 0, .iptr=&NID2, .defintval=1, TYPE_INT, 0}, \
|
||||
{"no-itti-threads", CONFIG_HLP_NOITTI, PARAMFLAG_BOOL, .iptr=&softmodem_params.no_itti, .defintval=0, TYPE_INT, 0}, \
|
||||
{"ldpc-offload-enable", CONFIG_HLP_LDPC_OFFLOAD, PARAMFLAG_BOOL, .iptr=&LDPC_OFFLOAD_FLAG, .defstrval=0, TYPE_INT, 0}, \
|
||||
{"sync-ref", CONFIG_HLP_SYNC_REF, 0, .uptr=&SYNC_REF, .defintval=0, TYPE_UINT, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -232,7 +224,6 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s3a = { config_checkstr_assign_integer, \
|
||||
{"MONOLITHIC", "PNF", "VNF","UE_STUB_PNF","UE_STUB_OFFNET","STANDALONE_PNF"}, \
|
||||
{NFAPI_MONOLITHIC, NFAPI_MODE_PNF, NFAPI_MODE_VNF,NFAPI_UE_STUB_PNF,NFAPI_UE_STUB_OFFNET,NFAPI_MODE_STANDALONE_PNF}, \
|
||||
@@ -326,8 +317,7 @@ typedef struct {
|
||||
uint64_t optmask;
|
||||
//THREAD_STRUCT thread_struct;
|
||||
char *rf_config_file;
|
||||
char *threadPoolConfig;
|
||||
int reorder_thread_disable;
|
||||
char *threadPoolConfig;
|
||||
int phy_test;
|
||||
int do_ra;
|
||||
int sa;
|
||||
@@ -353,9 +343,7 @@ typedef struct {
|
||||
int non_stop;
|
||||
int emulate_l1;
|
||||
int continuous_tx;
|
||||
int sync_ref;
|
||||
int nid1;
|
||||
int nid2;
|
||||
uint32_t sync_ref;
|
||||
int no_itti;
|
||||
int ldpc_offload_flag;
|
||||
} softmodem_params_t;
|
||||
@@ -375,7 +363,6 @@ extern uint16_t sl_ahead;
|
||||
extern uint16_t sf_ahead;
|
||||
extern int oai_exit;
|
||||
|
||||
void tx_func(void *param);
|
||||
void rx_func(void *param);
|
||||
void ru_tx_func(void *param);
|
||||
extern uint8_t nfapi_mode;
|
||||
|
||||
@@ -1244,7 +1244,6 @@ int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) {
|
||||
|
||||
int phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) {
|
||||
struct PHY_VARS_gNB_s *gNB = RC.gNB[0];
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
|
||||
gNB->UL_INFO.srs_ind = *ind;
|
||||
|
||||
@@ -1260,8 +1259,6 @@ int phy_nr_srs_indication(nfapi_nr_srs_indication_t *ind) {
|
||||
);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
//end NR phy indication
|
||||
|
||||
@@ -351,7 +351,7 @@ typedef struct
|
||||
uint16_t sl_bandwidth;
|
||||
//Absolute frequency of SL point A in KHz
|
||||
//n38 (2570-2620 Mhz), n47 (5855-5925 Mhz) are defined.
|
||||
uint32_t sl_frequency;
|
||||
uint64_t sl_frequency;
|
||||
|
||||
//Only 1 SCS-SpecificCarrier allowed for NR-SL communication
|
||||
uint16_t sl_grid_size;// bandwidth for each numerology
|
||||
@@ -363,7 +363,7 @@ typedef struct
|
||||
uint8_t sl_frequency_shift_7p5khz;
|
||||
//Indicates presence of +/-5Khz shift wrt FREF for V2X reference frequencies.
|
||||
//Possible values: {-1,0,1}
|
||||
uint8_t sl_value_N;
|
||||
int8_t sl_value_N;
|
||||
|
||||
} sl_nr_carrier_config_t;
|
||||
|
||||
|
||||
@@ -182,7 +182,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config)
|
||||
NFAPI_TRACE(NFAPI_TRACE_DEBUG, "This is the slot_ind queue size %ld in %s():%d\n",
|
||||
gnb_slot_ind_queue.num_items, __FUNCTION__, __LINE__);
|
||||
if (slot_ind) {
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
gNB->UL_INFO.frame = slot_ind->sfn;
|
||||
gNB->UL_INFO.slot = slot_ind->slot;
|
||||
|
||||
@@ -198,7 +197,6 @@ int nfapi_nr_vnf_p7_start(nfapi_vnf_p7_config_t* config)
|
||||
gNB->if_inst->NR_UL_indication(&gNB->UL_INFO);
|
||||
prev_slot = gNB->UL_INFO.slot;
|
||||
}
|
||||
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
free(slot_ind);
|
||||
slot_ind = NULL;
|
||||
}
|
||||
|
||||
@@ -76,11 +76,11 @@ void nr_fill_prach(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu) {
|
||||
|
||||
int prach_id = find_nr_prach(gNB,SFN,Slot,SEARCH_EXIST_OR_FREE);
|
||||
AssertFatal( ((prach_id>=0) && (prach_id<NUMBER_OF_NR_PRACH_MAX)) || (prach_id < 0),
|
||||
"illegal or no prach_id found!!! prach_id %d\n",prach_id);
|
||||
AssertFatal(((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX)), "illegal or no prach_id found!!! prach_id %d\n", prach_id);
|
||||
|
||||
gNB->prach_vars.list[prach_id].frame=SFN;
|
||||
gNB->prach_vars.list[prach_id].slot=Slot;
|
||||
LOG_D(NR_PHY,"Copying prach pdu %d bytes to index %d\n",(int)sizeof(*prach_pdu),prach_id);
|
||||
memcpy((void*)&gNB->prach_vars.list[prach_id].pdu,(void*)prach_pdu,sizeof(*prach_pdu));
|
||||
|
||||
}
|
||||
|
||||
@@ -74,8 +74,8 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t
|
||||
NR_UL_gNB_HARQ_t *harq = ulsch->harq_process;
|
||||
if (ulsch_pdu->pusch_data.new_data_indicator)
|
||||
harq->harq_to_be_cleared = true;
|
||||
LOG_D(PHY,
|
||||
"%d.%d RNTI %x HARQ PID %d new data indicator %d\n",
|
||||
LOG_D(NR_PHY,
|
||||
"NEW ULSCH %d.%d RNTI %x HARQ PID %d new data indicator %d\n",
|
||||
frame,
|
||||
slot,
|
||||
ulsch_pdu->rnti,
|
||||
@@ -98,8 +98,17 @@ void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame)
|
||||
// assuming UE disconnected or some other error occurred
|
||||
for (int i = 0; i < gNB->max_nb_pusch; i++) {
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[i];
|
||||
if (ulsch->active && (((frame - ulsch->frame + 1024) % 1024) > NUMBER_FRAMES_PHY_UE_INACTIVE))
|
||||
int diff = (frame - ulsch->frame + 1024) & 1023;
|
||||
if (ulsch->active && diff > NUMBER_FRAMES_PHY_UE_INACTIVE && diff < 100) {
|
||||
ulsch->active = false;
|
||||
LOG_D(NR_PHY,
|
||||
"Frame %d: resetting ulsch %d harq %d (programmed in %d.%d)\n",
|
||||
frame,
|
||||
i,
|
||||
ulsch->harq_pid,
|
||||
ulsch->frame,
|
||||
ulsch->slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1409,7 +1409,7 @@ static void nr_pusch_symbol_processing(void *arg)
|
||||
|
||||
if (gNB->pusch_vars[ulsch_id].ul_valid_re_per_slot[symbol] == 0)
|
||||
continue;
|
||||
int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;
|
||||
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
inner_rx(gNB,
|
||||
ulsch_id,
|
||||
slot,
|
||||
@@ -1591,7 +1591,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB,
|
||||
|
||||
// extract the first dmrs for the channel level computation
|
||||
// extract the data in the OFDM frame, to the start of the array
|
||||
int soffset = (slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size;
|
||||
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
|
||||
nb_re_pusch = (nb_re_pusch + 15) & ~15;
|
||||
|
||||
|
||||
@@ -501,7 +501,7 @@ void nr_decode_pucch1(c16_t **rxdataF,
|
||||
* Implement TS 38.211 Subclause 6.3.2.4.1 Sequence modulation
|
||||
*
|
||||
*/
|
||||
const int soffset = (nr_tti_tx & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
const int soffset = (nr_tti_tx % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
// lprime is the index of the OFDM symbol in the slot that corresponds to the first OFDM symbol of the PUCCH transmission in the slot given by [5, TS 38.213]
|
||||
const int lprime = startingSymbolIndex;
|
||||
// mcs = 0 except for PUCCH format 0
|
||||
@@ -1021,14 +1021,10 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
|
||||
//extract pucch and dmrs first
|
||||
|
||||
int l2 = pucch_pdu->start_symbol_index;
|
||||
|
||||
int soffset = (slot & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
|
||||
int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
int re_offset[2];
|
||||
re_offset[0] =
|
||||
(12 * (pucch_pdu->prb_start + pucch_pdu->bwp_start) + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size;
|
||||
if (re_offset[0]>= frame_parms->ofdm_symbol_size)
|
||||
re_offset[0]-=frame_parms->ofdm_symbol_size;
|
||||
if (pucch_pdu->freq_hop_flag == 0)
|
||||
re_offset[1] = re_offset[0];
|
||||
else {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/defs_RU.h"
|
||||
#include "PHY/CODING/nrSmallBlock/nr_small_block_defs.h"
|
||||
#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
@@ -75,7 +76,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB,
|
||||
c16_t **rxdataF = gNB->common_vars.rxdataF;
|
||||
const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
|
||||
const uint16_t n_symbols = (slot&3)*frame_parms->symbols_per_slot; // number of symbols until this slot
|
||||
const uint16_t n_symbols = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot; // number of symbols until this slot
|
||||
const uint8_t l0 = frame_parms->symbols_per_slot - 1 - srs_pdu->time_start_position; // starting symbol in this slot
|
||||
const uint64_t symbol_offset = (n_symbols+l0)*frame_parms->ofdm_symbol_size;
|
||||
const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*NR_NB_SC_PER_RB;
|
||||
|
||||
@@ -197,7 +197,7 @@ typedef struct {
|
||||
|
||||
#define NUMBER_OF_NR_RU_PRACH_MAX 8
|
||||
#define NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX 12
|
||||
|
||||
#define RU_RX_SLOT_DEPTH 4
|
||||
typedef struct RU_proc_t_s {
|
||||
/// Pointer to associated RU descriptor
|
||||
struct RU_t_s *ru;
|
||||
|
||||
@@ -562,7 +562,6 @@ typedef struct PHY_VARS_gNB_s {
|
||||
PHY_MEASUREMENTS_gNB measurements;
|
||||
NR_IF_Module_t *if_inst;
|
||||
NR_UL_IND_t UL_INFO;
|
||||
pthread_mutex_t UL_INFO_mutex;
|
||||
|
||||
/// NFAPI RX ULSCH information
|
||||
nfapi_nr_rx_data_pdu_t rx_pdu_list[MAX_UL_PDUS_PER_SLOT];
|
||||
@@ -640,8 +639,6 @@ typedef struct PHY_VARS_gNB_s {
|
||||
|
||||
int ldpc_offload_flag;
|
||||
|
||||
int reorder_thread_disable;
|
||||
|
||||
int max_ldpc_iterations;
|
||||
/// indicate the channel estimation technique in time domain
|
||||
int chest_time;
|
||||
@@ -694,8 +691,8 @@ typedef struct PHY_VARS_gNB_s {
|
||||
time_stats_t rx_pusch_init_stats;
|
||||
time_stats_t rx_pusch_symbol_processing_stats;
|
||||
time_stats_t ul_indication_stats;
|
||||
time_stats_t slot_indication_stats;
|
||||
time_stats_t schedule_response_stats;
|
||||
time_stats_t ulsch_decoding_stats;
|
||||
time_stats_t ulsch_ldpc_decoding_stats;
|
||||
time_stats_t ulsch_deinterleaving_stats;
|
||||
time_stats_t ulsch_channel_estimation_stats;
|
||||
@@ -719,6 +716,7 @@ typedef struct PHY_VARS_gNB_s {
|
||||
notifiedFIFO_t L1_tx_free;
|
||||
notifiedFIFO_t L1_tx_filled;
|
||||
notifiedFIFO_t L1_tx_out;
|
||||
notifiedFIFO_t L1_rx_out;
|
||||
notifiedFIFO_t resp_RU_tx;
|
||||
tpool_t threadPool;
|
||||
int nbSymb;
|
||||
@@ -796,9 +794,7 @@ union ldpcReqUnion {
|
||||
|
||||
typedef struct processingData_L1 {
|
||||
int frame_rx;
|
||||
int frame_tx;
|
||||
int slot_rx;
|
||||
int slot_tx;
|
||||
openair0_timestamp timestamp_tx;
|
||||
PHY_VARS_gNB *gNB;
|
||||
} processingData_L1_t;
|
||||
@@ -812,6 +808,8 @@ typedef enum {
|
||||
typedef struct processingData_L1tx {
|
||||
int frame;
|
||||
int slot;
|
||||
int frame_rx;
|
||||
int slot_rx;
|
||||
openair0_timestamp timestamp_tx;
|
||||
PHY_VARS_gNB *gNB;
|
||||
nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu[NFAPI_NR_MAX_NB_CORESETS];
|
||||
@@ -826,4 +824,9 @@ typedef struct processingData_L1tx {
|
||||
int sched_response_id;
|
||||
} processingData_L1tx_t;
|
||||
|
||||
typedef struct processingData_L1rx {
|
||||
int frame_rx;
|
||||
int slot_rx;
|
||||
PHY_VARS_gNB *gNB;
|
||||
} processingData_L1rx_t;
|
||||
#endif
|
||||
|
||||
@@ -55,7 +55,7 @@ void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot,
|
||||
|
||||
uint8_t i_ssb = dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex;
|
||||
|
||||
LOG_D(PHY,"%d.%d : ssb index %d pbch_pdu: %x\n",frame,slot,i_ssb,dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload);
|
||||
LOG_D(NR_PHY,"%d.%d : ssb index %d pbch_pdu: %x\n",frame,slot,i_ssb,dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload);
|
||||
if (msgTx->ssb[i_ssb].active)
|
||||
AssertFatal(1==0,"SSB PDU with index %d already active\n",i_ssb);
|
||||
else {
|
||||
@@ -109,7 +109,7 @@ void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, int frame, int slot
|
||||
for (int id = 0; id < NR_SYMBOLS_PER_SLOT; id++) {
|
||||
NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[id];
|
||||
if (csirs->active == 0) {
|
||||
LOG_D(PHY,"Frame %d Slot %d CSI_RS with ID %d is now active\n",frame,slot,id);
|
||||
LOG_D(NR_PHY,"Frame %d Slot %d CSI_RS with ID %d is now active\n",frame,slot,id);
|
||||
csirs->active = 1;
|
||||
memcpy((void*)&csirs->csirs_pdu, (void*)csirs_pdu, sizeof(nfapi_nr_dl_tti_csi_rs_pdu));
|
||||
found = 1;
|
||||
@@ -156,21 +156,9 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO)
|
||||
uint8_t number_tx_data_pdu = (TX_req == NULL) ? 0 : TX_req->Number_of_PDUs;
|
||||
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC){
|
||||
|
||||
if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) {
|
||||
notifiedFIFO_elt_t *res=NULL;
|
||||
processingData_L1tx_t *msgTx=NULL;
|
||||
if (!gNB->reorder_thread_disable) {
|
||||
res = pullNotifiedFIFO(&gNB->L1_tx_free);
|
||||
if (res == NULL)
|
||||
return; // Tpool has been stopped, nothing to process
|
||||
msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
|
||||
} else {
|
||||
msgTx = gNB->msgDataTx; //newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0, &gNB->L1_tx_out,NULL);
|
||||
}
|
||||
/*const time_stats_t ts = exec_time_stats_NotifiedFIFO(res);
|
||||
merge_meas(&gNB->phy_proc_tx, &ts);
|
||||
*/
|
||||
msgTx = gNB->msgDataTx;
|
||||
msgTx->num_pdsch_slot = 0;
|
||||
msgTx->num_dl_pdcch = 0;
|
||||
msgTx->num_ul_pdcch = number_ul_dci_pdu;
|
||||
@@ -181,7 +169,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO)
|
||||
|
||||
for (int i=0;i<number_dl_pdu;i++) {
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i];
|
||||
LOG_D(PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType);
|
||||
LOG_D(NR_PHY,"NFAPI: dl_pdu %d : type %d\n",i,dl_tti_pdu->PDUType);
|
||||
switch (dl_tti_pdu->PDUType) {
|
||||
case NFAPI_NR_DL_TTI_SSB_PDU_TYPE:
|
||||
handle_nr_nfapi_ssb_pdu(msgTx,frame,slot,
|
||||
@@ -189,18 +177,18 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO)
|
||||
break;
|
||||
|
||||
case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE:
|
||||
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot);
|
||||
LOG_D(NR_PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot);
|
||||
msgTx->pdcch_pdu[msgTx->num_dl_pdcch] = dl_tti_pdu->pdcch_pdu;
|
||||
msgTx->num_dl_pdcch++;
|
||||
break;
|
||||
|
||||
case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE:
|
||||
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot);
|
||||
LOG_D(NR_PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot);
|
||||
handle_nfapi_nr_csirs_pdu(msgTx,frame,slot,&dl_tti_pdu->csi_rs_pdu);
|
||||
break;
|
||||
|
||||
case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE:
|
||||
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot);
|
||||
LOG_D(NR_PHY,"frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n",frame,slot,DL_req->SFN,DL_req->Slot);
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15;
|
||||
uint16_t pduIndex = pdsch_pdu_rel15->pduIndex;
|
||||
AssertFatal(TX_req->pdu_list[pduIndex].num_TLV == 1, "TX_req->pdu_list[%d].num_TLV %d != 1\n",
|
||||
@@ -222,29 +210,27 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO)
|
||||
* released only when both threads are done with it.
|
||||
*/
|
||||
inc_ref_sched_response(Sched_INFO->sched_response_id);
|
||||
if (!gNB->reorder_thread_disable)
|
||||
pushNotifiedFIFO(&gNB->L1_tx_filled,res);
|
||||
}
|
||||
|
||||
for (int i = 0; i < number_ul_tti_pdu; i++) {
|
||||
switch (UL_tti_req->pdus_list[i].pdu_type) {
|
||||
case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE:
|
||||
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
|
||||
LOG_D(NR_PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUSCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
|
||||
nr_fill_ulsch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu);
|
||||
break;
|
||||
case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE:
|
||||
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
|
||||
LOG_D(NR_PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PUCCH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
|
||||
nr_fill_pucch(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu);
|
||||
break;
|
||||
case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE:
|
||||
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
|
||||
LOG_D(NR_PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu;
|
||||
nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
if (gNB->RU_list[0]->if_south == LOCAL_RF ||
|
||||
gNB->RU_list[0]->if_south == REMOTE_IF5) nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
break;
|
||||
case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE:
|
||||
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
|
||||
LOG_D(NR_PHY,"frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
|
||||
nr_fill_srs(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu);
|
||||
break;
|
||||
}
|
||||
@@ -267,7 +253,9 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO)
|
||||
}
|
||||
|
||||
/* this thread is done with the sched_info, decrease the reference counter */
|
||||
deref_sched_response(Sched_INFO->sched_response_id);
|
||||
|
||||
if (slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) {
|
||||
LOG_D(NR_PHY, "Calling dref_sched_response for id %d in %d.%d (sched_response)\n", Sched_INFO->sched_response_id, frame, slot);
|
||||
deref_sched_response(Sched_INFO->sched_response_id);
|
||||
}
|
||||
stop_meas(&gNB->schedule_response_stats);
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot) {
|
||||
int prach_id=find_nr_prach(gNB,frame,slot,SEARCH_EXIST);
|
||||
|
||||
if (prach_id>=0) {
|
||||
LOG_D(NR_PHY,"%d.%d Got prach entry id %d\n",frame,slot,prach_id);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_vars.list[prach_id].pdu;
|
||||
uint8_t prachStartSymbol;
|
||||
uint8_t N_dur = get_nr_prach_duration(prach_pdu->prach_format);
|
||||
@@ -140,9 +141,9 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot) {
|
||||
&max_preamble[0],
|
||||
&max_preamble_energy[0],
|
||||
&max_preamble_delay[0]);
|
||||
|
||||
LOG_D(NR_PHY,"Freeing PRACH entry %d\n",prach_id);
|
||||
free_nr_prach_entry(gNB,prach_id);
|
||||
LOG_D(PHY,"[RAPROC] Frame %d, slot %d, occasion %d (prachStartSymbol %d) : Most likely preamble %d, energy %d.%d dB delay %d (prach_energy counter %d)\n",
|
||||
LOG_D(NR_PHY,"[RAPROC] Frame %d, slot %d, occasion %d (prachStartSymbol %d) : Most likely preamble %d, energy %d.%d dB delay %d (prach_energy counter %d)\n",
|
||||
frame,slot,prach_oc,prachStartSymbol,
|
||||
max_preamble[0],
|
||||
max_preamble_energy[0]/10,
|
||||
|
||||
@@ -242,7 +242,7 @@ void nr_fep_full(RU_t *ru, int slot) {
|
||||
|
||||
// remove_7_5_kHz(ru,proc->tti_rx<<1);
|
||||
// remove_7_5_kHz(ru,1+(proc->tti_rx<<1));
|
||||
int offset = (proc->tti_rx&3)*(fp->symbols_per_slot * fp->ofdm_symbol_size);
|
||||
int offset = (proc->tti_rx % RU_RX_SLOT_DEPTH) * (fp->symbols_per_slot * fp->ofdm_symbol_size);
|
||||
for (l = 0; l < fp->symbols_per_slot; l++) {
|
||||
for (aa = 0; aa < fp->nb_antennas_rx; aa++) {
|
||||
nr_slot_fep_ul(fp,
|
||||
@@ -378,7 +378,7 @@ void nr_fep(void* arg) {
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+aid, 1);
|
||||
|
||||
int offset = (tti_rx&3) * fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
int offset = (tti_rx % RU_RX_SLOT_DEPTH) * fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
for (int l = startSymbol; l <= endSymbol; l++)
|
||||
nr_slot_fep_ul(fp,
|
||||
ru->common.rxdata[aid],
|
||||
|
||||
@@ -272,10 +272,11 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
}
|
||||
|
||||
if (crc_valid && !check_abort(&ulsch_harq->abort_decode) && !gNB->pusch_vars[rdata->ulsch_id].DTX) {
|
||||
LOG_D(PHY,
|
||||
"[gNB %d] ULSCH: Setting ACK for SFN/SF %d.%d (rnti %x, pid %d, ndi %d, status %d, round %d, TBS %d, Max interation "
|
||||
LOG_D(NR_PHY,
|
||||
"[gNB %d] ULSCH %d: Setting ACK for SFN/SF %d.%d (rnti %x, pid %d, ndi %d, status %d, round %d, TBS %d, Max interation "
|
||||
"(all seg) %d)\n",
|
||||
gNB->Mod_id,
|
||||
rdata->ulsch_id,
|
||||
ulsch->frame,
|
||||
ulsch->slot,
|
||||
ulsch->rnti,
|
||||
@@ -316,7 +317,7 @@ static void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req)
|
||||
if (ulsch_harq->ulsch_pdu.mcs_index == 0 && dumpsig==1) {
|
||||
int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0;
|
||||
|
||||
LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(ulsch_harq->slot&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1);
|
||||
LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(ulsch_harq->slot%RU_RX_SLOT_DEPTH)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1);
|
||||
LOG_M("rxsigF0_ext.m","rxsF0_ext",
|
||||
&gNB->pusch_vars[0].rxdataF_ext[0][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB *
|
||||
ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB *
|
||||
@@ -400,7 +401,6 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int
|
||||
//--------------------- ULSCH decoding ---------------------
|
||||
//----------------------------------------------------------
|
||||
|
||||
start_meas(&gNB->ulsch_decoding_stats);
|
||||
int nbDecode =
|
||||
nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G);
|
||||
|
||||
@@ -410,9 +410,6 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int
|
||||
|
||||
void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag)
|
||||
{
|
||||
if (!get_softmodem_params()->reorder_thread_disable)
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process;
|
||||
NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti);
|
||||
@@ -467,7 +464,13 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id,
|
||||
__attribute__((unused))
|
||||
int off = ((pusch_pdu->rb_size&1) == 1)? 4:0;
|
||||
|
||||
LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(slot_rx&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1);
|
||||
LOG_M("rxsigF0.m",
|
||||
"rxsF0",
|
||||
&gNB->common_vars
|
||||
.rxdataF[0][(slot_rx % RU_RX_SLOT_DEPTH) * gNB->frame_parms.ofdm_symbol_size * gNB->frame_parms.symbols_per_slot],
|
||||
gNB->frame_parms.ofdm_symbol_size * gNB->frame_parms.symbols_per_slot,
|
||||
1,
|
||||
1);
|
||||
LOG_M("chestF0.m",
|
||||
"chF0",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates[0][pusch_pdu->start_symbol_index * gNB->frame_parms.ofdm_symbol_size],
|
||||
@@ -494,7 +497,14 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id,
|
||||
1,
|
||||
0);
|
||||
if (gNB->frame_parms.nb_antennas_rx > 1) {
|
||||
LOG_M("rxsigF1.m","rxsF1",&gNB->common_vars.rxdataF[1][(slot_rx&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1);
|
||||
LOG_M(
|
||||
"rxsigF1.m",
|
||||
"rxsF1",
|
||||
&gNB->common_vars
|
||||
.rxdataF[1][(slot_rx % RU_RX_SLOT_DEPTH) * gNB->frame_parms.ofdm_symbol_size * gNB->frame_parms.symbols_per_slot],
|
||||
gNB->frame_parms.ofdm_symbol_size * gNB->frame_parms.symbols_per_slot,
|
||||
1,
|
||||
1);
|
||||
LOG_M("chestF1.m",
|
||||
"chF1",
|
||||
&gNB->pusch_vars[0].ul_ch_estimates[1][pusch_pdu->start_symbol_index * gNB->frame_parms.ofdm_symbol_size],
|
||||
@@ -557,9 +567,6 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id,
|
||||
}
|
||||
|
||||
gNB->UL_INFO.rx_ind.number_of_pdus++;
|
||||
|
||||
if (!get_softmodem_params()->reorder_thread_disable)
|
||||
pthread_mutex_unlock(&gNB->UL_INFO_mutex);
|
||||
}
|
||||
|
||||
// Function to fill UL RB mask to be used for N0 measurements
|
||||
@@ -834,9 +841,9 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id];
|
||||
NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process;
|
||||
AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid);
|
||||
|
||||
if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) {
|
||||
LOG_D(PHY, "PUSCH ID %d with RNTI %x detection started in frame %d slot %d\n", ULSCH_id, ulsch->rnti, frame_rx, slot_rx);
|
||||
|
||||
int num_dmrs = 0;
|
||||
for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++)
|
||||
num_dmrs += (ulsch_harq->ulsch_pdu.ul_dmrs_symb_pos >> s) & 1;
|
||||
@@ -941,7 +948,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
|
||||
delNotifiedFIFO_elt(req);
|
||||
totalDecode--;
|
||||
}
|
||||
stop_meas(&gNB->ulsch_decoding_stats);
|
||||
for (int i = 0; i < gNB->max_nb_srs; i++) {
|
||||
NR_gNB_SRS_t *srs = &gNB->srs[i];
|
||||
if (srs) {
|
||||
|
||||
@@ -895,6 +895,7 @@ int main(int argc, char **argv)
|
||||
msgDataTx->slot = slot;
|
||||
msgDataTx->frame = frame;
|
||||
memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
|
||||
gNB->msgDataTx = msgDataTx;
|
||||
|
||||
// Buffers to store internal memory of slot process
|
||||
int rx_size = (((14 * frame_parms->N_RB_DL * 12 * sizeof(int32_t)) + 15) >> 4) << 4;
|
||||
|
||||
@@ -563,6 +563,7 @@ int main(int argc, char *argv[])
|
||||
notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_free, NULL);
|
||||
processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
|
||||
msgDataTx->slot = -1;
|
||||
gNB->msgDataTx = msgDataTx;
|
||||
//gNB_config = &gNB->gNB_config;
|
||||
|
||||
//memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
|
||||
@@ -921,7 +922,6 @@ int main(int argc, char *argv[])
|
||||
reset_meas(&gNB->rx_pusch_stats);
|
||||
reset_meas(&gNB->rx_pusch_init_stats);
|
||||
reset_meas(&gNB->rx_pusch_symbol_processing_stats);
|
||||
reset_meas(&gNB->ulsch_decoding_stats);
|
||||
reset_meas(&gNB->ulsch_channel_estimation_stats);
|
||||
reset_meas(&UE->ulsch_ldpc_encoding_stats);
|
||||
reset_meas(&UE->ulsch_rate_matching_stats);
|
||||
@@ -1546,7 +1546,6 @@ int main(int argc, char *argv[])
|
||||
printStatIndent2(&gNB->ulsch_channel_estimation_stats, "ULSCH channel estimation time");
|
||||
printStatIndent2(&gNB->rx_pusch_init_stats, "RX PUSCH Initialization time");
|
||||
printStatIndent2(&gNB->rx_pusch_symbol_processing_stats, "RX PUSCH Symbol Processing time");
|
||||
printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time");
|
||||
|
||||
printf("\nUE TX\n");
|
||||
printStatIndent(&UE->ulsch_encoding_stats,"ULSCH total encoding time");
|
||||
|
||||
@@ -57,4 +57,5 @@ MESSAGE_DEF(RRC_MAC_DRX_CONFIG_REQ, MESSAGE_PRIORITY_MED, rrc_mac_drx_config_req
|
||||
// gNB
|
||||
MESSAGE_DEF(NR_RRC_MAC_CCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacCcchDataInd, nr_rrc_mac_ccch_data_ind)
|
||||
MESSAGE_DEF(NR_RRC_MAC_BCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacBcchDataInd, nr_rrc_mac_bcch_data_ind)
|
||||
MESSAGE_DEF(NR_RRC_MAC_SBCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcMacSBcchDataInd, nr_rrc_mac_sbcch_data_ind)
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#define RRC_MAC_BCCH_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_req
|
||||
#define RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_data_ind
|
||||
#define NR_RRC_MAC_BCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_bcch_data_ind
|
||||
#define NR_RRC_MAC_SBCCH_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nr_rrc_mac_sbcch_data_ind
|
||||
|
||||
#define RRC_MAC_BCCH_MBMS_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_req
|
||||
#define RRC_MAC_BCCH_MBMS_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.rrc_mac_bcch_mbms_data_ind
|
||||
@@ -119,6 +120,17 @@ typedef struct NRRrcMacBcchDataInd_s {
|
||||
uint8_t rsrp;
|
||||
} NRRrcMacBcchDataInd;
|
||||
|
||||
typedef struct NRRrcMacSBcchDataInd_s {
|
||||
uint32_t frame;
|
||||
uint8_t slot;
|
||||
uint32_t sdu_size;
|
||||
uint8_t sdu[BCCH_SDU_SIZE];
|
||||
uint8_t gnb_index;
|
||||
uint16_t rx_slss_id;
|
||||
uint8_t rsrq;
|
||||
uint8_t rsrp;
|
||||
} NRRrcMacSBcchDataInd;
|
||||
|
||||
typedef struct RrcMacBcchMbmsDataReq_s {
|
||||
uint32_t frame;
|
||||
uint32_t sdu_size;
|
||||
|
||||
@@ -9,6 +9,7 @@ add_library(e2_ran_func_cuup STATIC
|
||||
O-RAN/ran_func_kpm.c # this file should only contain PDCP-U/GTP; to be done in the future
|
||||
../flexric/test/rnd/fill_rnd_data_kpm.c # this dependancy will be taken out once RAN Function Definition is implemented
|
||||
O-RAN/ran_func_rc.c # this file should only contain PDCP-U/GTP; to be done in the future
|
||||
O-RAN/ran_func_rc_subs.c
|
||||
../flexric/test/rnd/fill_rnd_data_rc.c # this dependancy will be taken out once RAN Function Definition is implemented
|
||||
)
|
||||
|
||||
@@ -27,7 +28,9 @@ add_library(e2_ran_func_du_cucp_cuup STATIC
|
||||
../flexric/test/rnd/fill_rnd_data_kpm.c # this dependancy will be taken out once RAN Function Definition is implemented
|
||||
O-RAN/ran_func_rc.c # this file should only contain RRC/PDCP-C; to be done in the future
|
||||
# when nr-softmodem is divided in separate executables
|
||||
O-RAN/ran_func_rc_subs.c
|
||||
../flexric/test/rnd/fill_rnd_data_rc.c # this dependancy will be taken out once RAN Function Definition is implemented
|
||||
../flexric/src/sm/rc_sm/ie/rc_data_ie.c
|
||||
CUSTOMIZED/ran_func_mac.c
|
||||
CUSTOMIZED/ran_func_rlc.c
|
||||
CUSTOMIZED/ran_func_slice.c
|
||||
@@ -36,5 +39,5 @@ add_library(e2_ran_func_du_cucp_cuup STATIC
|
||||
../flexric/test/rnd/fill_rnd_data_slice.c
|
||||
)
|
||||
|
||||
target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj)
|
||||
target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj)
|
||||
target_compile_definitions(e2_ran_func_du_cucp_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_DU NGRAN_GNB_CUCP NGRAN_GNB_CUUP)
|
||||
|
||||
@@ -20,25 +20,24 @@
|
||||
*/
|
||||
|
||||
#include "ran_func_rc.h"
|
||||
#include "ran_func_rc_subs.h"
|
||||
#include "ran_func_rc_extern.h"
|
||||
#include "../../flexric/test/rnd/fill_rnd_data_rc.h" // this dependancy will be taken out once RAN Function Definition is implemented
|
||||
#include "../../flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h"
|
||||
#include "../../flexric/src/sm/rc_sm/ie/ir/ran_param_list.h"
|
||||
#include "../../flexric/src/agent/e2_agent_api.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include "common/ran_context.h"
|
||||
|
||||
// Please note: current implementation doesn't take split architecture into account, neither CU/DU nor CU-UP/CU-CP
|
||||
static pthread_once_t once_rc_mutex = PTHREAD_ONCE_INIT;
|
||||
static rc_subs_data_t rc_subs_data = {0};
|
||||
static pthread_mutex_t rc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
bool read_rc_sm(void* data)
|
||||
static void init_once_rc(void)
|
||||
{
|
||||
assert(data != NULL);
|
||||
// assert(data->type == RAN_CTRL_STATS_V1_03);
|
||||
assert(0!=0 && "Not implemented");
|
||||
|
||||
return true;
|
||||
init_rc_subs_data(&rc_subs_data);
|
||||
}
|
||||
|
||||
void read_rc_setup_sm(void* data)
|
||||
@@ -47,8 +46,175 @@ void read_rc_setup_sm(void* data)
|
||||
// assert(data->type == RAN_CTRL_V1_3_AGENT_IF_E2_SETUP_ANS_V0);
|
||||
rc_e2_setup_t* rc = (rc_e2_setup_t*)data;
|
||||
rc->ran_func_def = fill_rc_ran_func_def();
|
||||
|
||||
// E2 Setup Request is sent periodically until the connection is established
|
||||
// RC subscritpion data should be initialized only once
|
||||
const int ret = pthread_once(&once_rc_mutex, init_once_rc);
|
||||
DevAssert(ret == 0);
|
||||
}
|
||||
|
||||
|
||||
RB_PROTOTYPE(ric_id_2_param_id_trees, ric_req_id_s, entries, cmp_ric_req_id);
|
||||
|
||||
static ue_id_e2sm_t fill_ue_id_data(const gNB_RRC_UE_t *rrc_ue_context)
|
||||
{
|
||||
ue_id_e2sm_t ue_id = {0};
|
||||
|
||||
// Check the E2 node type
|
||||
#if defined (NGRAN_GNB_CUUP) && defined (NGRAN_GNB_CUCP)
|
||||
ue_id.type = GNB_UE_ID_E2SM;
|
||||
if (RC.nrrrc[0]->node_type == ngran_gNB_CU) {
|
||||
// gNB-CU UE F1AP ID List
|
||||
// C-ifCUDUseparated
|
||||
ue_id.gnb.gnb_cu_ue_f1ap_lst_len = 1;
|
||||
ue_id.gnb.gnb_cu_ue_f1ap_lst = calloc(ue_id.gnb.gnb_cu_ue_f1ap_lst_len, sizeof(uint32_t));
|
||||
assert(ue_id.gnb.gnb_cu_ue_f1ap_lst != NULL && "Memory exhausted");
|
||||
|
||||
for(size_t i = 0; i < ue_id.gnb.gnb_cu_ue_f1ap_lst_len; i++) {
|
||||
ue_id.gnb.gnb_cu_ue_f1ap_lst[i] = rrc_ue_context->rrc_ue_id;
|
||||
}
|
||||
} else if (RC.nrrrc[0]->node_type == ngran_gNB_CUCP) {
|
||||
//gNB-CU-CP UE E1AP ID List
|
||||
//C-ifCPUPseparated
|
||||
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len = 1;
|
||||
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst = calloc(ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len, sizeof(uint32_t));
|
||||
assert(ue_id.gnb.gnb_cu_cp_ue_e1ap_lst != NULL && "Memory exhausted");
|
||||
|
||||
for(size_t i = 0; i < ue_id.gnb.gnb_cu_cp_ue_e1ap_lst_len; i++) {
|
||||
ue_id.gnb.gnb_cu_cp_ue_e1ap_lst[i] = rrc_ue_context->rrc_ue_id;
|
||||
}
|
||||
} else if (RC.nrrrc[0]->node_type == ngran_gNB_DU) {
|
||||
assert(false && "RRC state change cannot be triggered from DU\n");
|
||||
}
|
||||
|
||||
#elif defined (NGRAN_GNB_CUUP)
|
||||
assert(false && "RRC state change cannot be triggered from CU-UP\n");
|
||||
|
||||
#endif
|
||||
|
||||
ue_id.gnb.amf_ue_ngap_id = rrc_ue_context->rrc_ue_id;
|
||||
ue_id.gnb.guami.amf_ptr = rrc_ue_context->ue_guami.amf_pointer;
|
||||
ue_id.gnb.guami.amf_region_id = rrc_ue_context->ue_guami.amf_region_id;
|
||||
ue_id.gnb.guami.amf_set_id = rrc_ue_context->ue_guami.amf_set_id;
|
||||
ue_id.gnb.guami.plmn_id.mcc = rrc_ue_context->ue_guami.mcc;
|
||||
ue_id.gnb.guami.plmn_id.mnc = rrc_ue_context->ue_guami.mnc;
|
||||
ue_id.gnb.guami.plmn_id.mnc_digit_len = rrc_ue_context->ue_guami.mnc_len;
|
||||
|
||||
return ue_id;
|
||||
}
|
||||
|
||||
static seq_ran_param_t fill_rrc_state_change_seq_ran(const rc_sm_rrc_state_e rrc_state)
|
||||
{
|
||||
seq_ran_param_t seq_ran_param = {0};
|
||||
|
||||
seq_ran_param.ran_param_id = RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID;
|
||||
seq_ran_param.ran_param_val.type = ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE;
|
||||
seq_ran_param.ran_param_val.flag_false = calloc(1, sizeof(ran_parameter_value_t));
|
||||
assert(seq_ran_param.ran_param_val.flag_false != NULL && "Memory exhausted");
|
||||
seq_ran_param.ran_param_val.flag_false->type = INTEGER_RAN_PARAMETER_VALUE;
|
||||
seq_ran_param.ran_param_val.flag_false->int_ran = rrc_state;
|
||||
|
||||
return seq_ran_param;
|
||||
}
|
||||
|
||||
static rc_ind_data_t* fill_ue_rrc_state_change(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm_rrc_state_e rrc_state)
|
||||
{
|
||||
rc_ind_data_t* rc_ind = calloc(1, sizeof(rc_ind_data_t));
|
||||
assert(rc_ind != NULL && "Memory exhausted");
|
||||
|
||||
// Generate Indication Header
|
||||
rc_ind->hdr.format = FORMAT_1_E2SM_RC_IND_HDR;
|
||||
rc_ind->hdr.frmt_1.ev_trigger_id = NULL;
|
||||
|
||||
// Generate Indication Message
|
||||
rc_ind->msg.format = FORMAT_2_E2SM_RC_IND_MSG;
|
||||
|
||||
//Sequence of UE Identifier
|
||||
//[1-65535]
|
||||
rc_ind->msg.frmt_2.sz_seq_ue_id = 1;
|
||||
rc_ind->msg.frmt_2.seq_ue_id = calloc(rc_ind->msg.frmt_2.sz_seq_ue_id, sizeof(seq_ue_id_t));
|
||||
assert(rc_ind->msg.frmt_2.seq_ue_id != NULL && "Memory exhausted");
|
||||
|
||||
// UE ID
|
||||
// Mandatory
|
||||
// 9.3.10
|
||||
rc_ind->msg.frmt_2.seq_ue_id[0].ue_id = fill_ue_id_data(rrc_ue_context);
|
||||
|
||||
// Sequence of
|
||||
// RAN Parameter
|
||||
// [1- 65535]
|
||||
rc_ind->msg.frmt_2.seq_ue_id[0].sz_seq_ran_param = 1;
|
||||
rc_ind->msg.frmt_2.seq_ue_id[0].seq_ran_param = calloc(rc_ind->msg.frmt_2.seq_ue_id[0].sz_seq_ran_param, sizeof(seq_ran_param_t));
|
||||
assert(rc_ind->msg.frmt_2.seq_ue_id[0].seq_ran_param != NULL && "Memory exhausted");
|
||||
rc_ind->msg.frmt_2.seq_ue_id[0].seq_ran_param[0] = fill_rrc_state_change_seq_ran(rrc_state);
|
||||
|
||||
return rc_ind;
|
||||
}
|
||||
|
||||
void signal_rrc_state_changed_to(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm_rrc_state_e rrc_state)
|
||||
{
|
||||
pthread_mutex_lock(&rc_mutex);
|
||||
if (rc_subs_data.rb[RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID].rbh_root == NULL) {
|
||||
pthread_mutex_unlock(&rc_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
struct ric_req_id_s *node;
|
||||
RB_FOREACH(node, ric_id_2_param_id_trees, &rc_subs_data.rb[RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID]) {
|
||||
rc_ind_data_t* rc_ind_data = fill_ue_rrc_state_change(rrc_ue_context, rrc_state);
|
||||
|
||||
// Needs review: memory ownership of the type rc_ind_data_t is transferred to the E2 Agent. Bad
|
||||
async_event_agent_api(node->ric_req_id, rc_ind_data);
|
||||
printf( "Event for RIC Req ID %u generated\n", node->ric_req_id);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&rc_mutex);
|
||||
}
|
||||
|
||||
static void free_aperiodic_subscription(uint32_t ric_req_id)
|
||||
{
|
||||
remove_rc_subs_data(&rc_subs_data, ric_req_id);
|
||||
}
|
||||
|
||||
sm_ag_if_ans_t write_subs_rc_sm(void const* src)
|
||||
{
|
||||
assert(src != NULL); // && src->type == RAN_CTRL_SUBS_V1_03);
|
||||
|
||||
wr_rc_sub_data_t* wr_rc = (wr_rc_sub_data_t*)src;
|
||||
|
||||
assert(wr_rc->rc.ad != NULL && "Cannot be NULL");
|
||||
|
||||
// 9.2.1.2 RIC ACTION DEFINITION IE
|
||||
switch (wr_rc->rc.ad->format) {
|
||||
case FORMAT_1_E2SM_RC_ACT_DEF: {
|
||||
// Parameters to be Reported List
|
||||
// [1-65535]
|
||||
const uint32_t ric_req_id = wr_rc->ric_req_id;
|
||||
arr_ran_param_id_t* arr_ran_param_id = calloc(1, sizeof(arr_ran_param_id_t));
|
||||
assert(arr_ran_param_id != NULL && "Memory exhausted");
|
||||
arr_ran_param_id->len = wr_rc->rc.ad->frmt_1.sz_param_report_def;
|
||||
arr_ran_param_id->ran_param_id = calloc(arr_ran_param_id->len, sizeof(ran_param_id_e));
|
||||
|
||||
const size_t sz = arr_ran_param_id->len;
|
||||
for(size_t i = 0; i < sz; i++) {
|
||||
arr_ran_param_id->ran_param_id[i] = wr_rc->rc.ad->frmt_1.param_report_def[i].ran_param_id;
|
||||
}
|
||||
insert_rc_subs_data(&rc_subs_data, ric_req_id, arr_ran_param_id);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
AssertFatal(wr_rc->rc.ad->format == FORMAT_1_E2SM_RC_ACT_DEF, "Action Definition Format %d not yet implemented", wr_rc->rc.ad->format);
|
||||
}
|
||||
|
||||
sm_ag_if_ans_t ans = {.type = SUBS_OUTCOME_SM_AG_IF_ANS_V0};
|
||||
ans.subs_out.type = APERIODIC_SUBSCRIPTION_FLRC;
|
||||
ans.subs_out.aper.free_aper_subs = free_aperiodic_subscription;
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
sm_ag_if_ans_t write_ctrl_rc_sm(void const* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
@@ -94,42 +260,12 @@ sm_ag_if_ans_t write_ctrl_rc_sm(void const* data)
|
||||
return ans;
|
||||
}
|
||||
|
||||
static
|
||||
void* emulate_rrc_msg(void* ptr)
|
||||
|
||||
bool read_rc_sm(void* data)
|
||||
{
|
||||
uint32_t* ric_id = (uint32_t*)ptr;
|
||||
for(size_t i = 0; i < 5; ++i){
|
||||
usleep(rand()%4000);
|
||||
rc_ind_data_t* d = calloc(1, sizeof(rc_ind_data_t));
|
||||
assert(d != NULL && "Memory exhausted");
|
||||
*d = fill_rnd_rc_ind_data();
|
||||
async_event_agent_api(*ric_id, d);
|
||||
printf("Event for RIC Req ID %u generated\n", *ric_id);
|
||||
}
|
||||
assert(data != NULL);
|
||||
// assert(data->type == RAN_CTRL_STATS_V1_03);
|
||||
assert(0!=0 && "Not implemented");
|
||||
|
||||
free(ptr);
|
||||
return NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
pthread_t t_ran_ctrl;
|
||||
|
||||
sm_ag_if_ans_t write_subs_rc_sm(void const* src)
|
||||
{
|
||||
assert(src != NULL); // && src->type == RAN_CTRL_SUBS_V1_03);
|
||||
|
||||
wr_rc_sub_data_t* wr_rc = (wr_rc_sub_data_t*)src;
|
||||
printf("ric req id %d \n", wr_rc->ric_req_id);
|
||||
|
||||
uint32_t* ptr = malloc(sizeof(uint32_t));
|
||||
assert(ptr != NULL);
|
||||
*ptr = wr_rc->ric_req_id;
|
||||
|
||||
int rc = pthread_create(&t_ran_ctrl, NULL, emulate_rrc_msg, ptr);
|
||||
assert(rc == 0);
|
||||
|
||||
sm_ag_if_ans_t ans = {0};
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,13 +24,12 @@
|
||||
|
||||
#include "openair2/E2AP/flexric/src/agent/../sm/sm_io.h"
|
||||
|
||||
bool read_rc_sm(void *);
|
||||
|
||||
void read_rc_setup_sm(void* data);
|
||||
|
||||
sm_ag_if_ans_t write_ctrl_rc_sm(void const* data);
|
||||
|
||||
sm_ag_if_ans_t write_subs_rc_sm(void const* src);
|
||||
|
||||
#endif
|
||||
sm_ag_if_ans_t write_ctrl_rc_sm(void const* data);
|
||||
|
||||
bool read_rc_sm(void *);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef RAN_FUNC_SM_RAN_CTRL_EXTERN_AGENT_H
|
||||
#define RAN_FUNC_SM_RAN_CTRL_EXTERN_AGENT_H
|
||||
|
||||
#include "openair2/RRC/NR/nr_rrc_defs.h"
|
||||
|
||||
typedef enum { RC_SM_RRC_CONNECTED, RC_SM_RRC_INACTIVE, RC_SM_RRC_IDLE, RC_SM_RRC_ANY } rc_sm_rrc_state_e;
|
||||
void signal_rrc_state_changed_to(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm_rrc_state_e rrc_state);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "ran_func_rc_subs.h"
|
||||
#include "common/utils/assertions.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_NUM_RIC_REQ_ID 64
|
||||
|
||||
static pthread_mutex_t rc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
int cmp_ric_req_id(struct ric_req_id_s *c1, struct ric_req_id_s *c2)
|
||||
{
|
||||
if (c1->ric_req_id < c2->ric_req_id)
|
||||
return -1;
|
||||
|
||||
if (c1->ric_req_id > c2->ric_req_id)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RB_GENERATE(ric_id_2_param_id_trees, ric_req_id_s, entries, cmp_ric_req_id);
|
||||
|
||||
void init_rc_subs_data(rc_subs_data_t* rc_subs_data)
|
||||
{
|
||||
pthread_mutex_lock(&rc_mutex);
|
||||
|
||||
// Initialize hash table
|
||||
DevAssert(rc_subs_data->htable == NULL);
|
||||
|
||||
// Initialize RB trees
|
||||
// 1 RB tree = 1 ran_param_id => many ric_req_id(s)
|
||||
for (size_t i = 0; i < END_E2SM_RC_RAN_PARAM_ID; i++) {
|
||||
RB_INIT(&rc_subs_data->rb[i]);
|
||||
}
|
||||
|
||||
rc_subs_data->htable = hashtable_create(MAX_NUM_RIC_REQ_ID, NULL, free);
|
||||
assert(rc_subs_data->htable != NULL && "Memory exhausted");
|
||||
pthread_mutex_unlock(&rc_mutex);
|
||||
}
|
||||
|
||||
void insert_rc_subs_data(rc_subs_data_t* rc_subs_data, uint32_t ric_req_id, arr_ran_param_id_t* arr_ran_param_id)
|
||||
{
|
||||
pthread_mutex_lock(&rc_mutex);
|
||||
|
||||
// Insert in hash table
|
||||
DevAssert(rc_subs_data->htable != NULL);
|
||||
uint64_t key = ric_req_id;
|
||||
// Check if the subscription already exists
|
||||
AssertFatal(hashtable_is_key_exists(rc_subs_data->htable, key) == HASH_TABLE_KEY_NOT_EXISTS, "RIC req ID %d already subscribed", ric_req_id);
|
||||
arr_ran_param_id_t* data = malloc(sizeof(*data));
|
||||
assert(data != NULL);
|
||||
*data = *arr_ran_param_id;
|
||||
hashtable_rc_t ret = hashtable_insert(rc_subs_data->htable, key, data);
|
||||
assert(ret == HASH_TABLE_OK && "Hash table not ok");
|
||||
|
||||
// Insert in RB trees
|
||||
// 1 RB tree = 1 ran_param_id => many ric_req_id(s)
|
||||
const size_t sz = arr_ran_param_id->len;
|
||||
rb_ric_req_id_t *node = calloc(1, sizeof(*node));
|
||||
assert(node != NULL);
|
||||
node->ric_req_id = ric_req_id;
|
||||
for (size_t i = 0; i < sz; i++) {
|
||||
RB_INSERT(ric_id_2_param_id_trees, &rc_subs_data->rb[arr_ran_param_id->ran_param_id[i]], node);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&rc_mutex);
|
||||
}
|
||||
|
||||
void remove_rc_subs_data(rc_subs_data_t* rc_subs_data, uint32_t ric_req_id)
|
||||
{
|
||||
pthread_mutex_lock(&rc_mutex);
|
||||
DevAssert(rc_subs_data->htable != NULL);
|
||||
|
||||
uint64_t key = ric_req_id;
|
||||
// Get the array of ran_param_id(s)
|
||||
void *data = NULL;
|
||||
hashtable_rc_t ret = hashtable_get(rc_subs_data->htable, key, &data);
|
||||
AssertFatal(ret == HASH_TABLE_OK && data != NULL, "element for ue_id %d not found\n", ric_req_id);
|
||||
arr_ran_param_id_t arr_ran_param_id = *(arr_ran_param_id_t *)data;
|
||||
// Remove ric_req_id with its ran_param_id(s) from hash table
|
||||
ret = hashtable_remove(rc_subs_data->htable, key);
|
||||
|
||||
// Remove ric_req_id from each ran_param_id tree where subscribed
|
||||
rb_ric_req_id_t *node = calloc(1, sizeof(*node));
|
||||
assert(node != NULL);
|
||||
node->ric_req_id = ric_req_id;
|
||||
for (size_t i = 0; i < arr_ran_param_id.len; i++) {
|
||||
RB_REMOVE(ric_id_2_param_id_trees, &rc_subs_data->rb[arr_ran_param_id.ran_param_id[i]], node);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&rc_mutex);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef RAN_FUNC_SM_RAN_CTRL_SUBSCRIPTION_AGENT_H
|
||||
#define RAN_FUNC_SM_RAN_CTRL_SUBSCRIPTION_AGENT_H
|
||||
|
||||
#include "common/utils/hashtable/hashtable.h"
|
||||
#include "common/utils/collection/tree.h"
|
||||
|
||||
typedef enum {
|
||||
RRC_STATE_CHANGED_TO_E2SM_RC_RAN_PARAM_ID = 202, // 8.2.4 RAN Parameters for Report Service Style 4
|
||||
|
||||
END_E2SM_RC_RAN_PARAM_ID
|
||||
} ran_param_id_e;
|
||||
|
||||
typedef struct{
|
||||
size_t len;
|
||||
ran_param_id_e* ran_param_id;
|
||||
} arr_ran_param_id_t;
|
||||
|
||||
typedef struct ric_req_id_s {
|
||||
RB_ENTRY(ric_req_id_s) entries;
|
||||
uint32_t ric_req_id;
|
||||
} rb_ric_req_id_t;
|
||||
|
||||
typedef struct {
|
||||
RB_HEAD(ric_id_2_param_id_trees, ric_req_id_s) rb[END_E2SM_RC_RAN_PARAM_ID]; // 1 RB tree = (1 RAN Parameter ID) : (n RIC Request ID) => m RB tree = (m RAN Parameter ID) : (n RIC Request ID)
|
||||
hash_table_t* htable; // 1 Hash table = (n RIC Request ID) : (m RAN Parameter ID)
|
||||
} rc_subs_data_t;
|
||||
|
||||
|
||||
int cmp_ric_req_id(struct ric_req_id_s *c1, struct ric_req_id_s *c2);
|
||||
|
||||
void init_rc_subs_data(rc_subs_data_t* rc_subs_data);
|
||||
void insert_rc_subs_data(rc_subs_data_t* rc_subs_data, uint32_t ric_req_id, arr_ran_param_id_t* arr_ran_param_id);
|
||||
void remove_rc_subs_data(rc_subs_data_t* rc_subs_data, uint32_t ric_req_id);
|
||||
|
||||
#endif
|
||||
+19
-5
@@ -98,7 +98,7 @@ git submodule update
|
||||
```bash
|
||||
git clone https://gitlab.eurecom.fr/mosaic5g/flexric flexric
|
||||
cd flexric/
|
||||
git checkout 70dd779f5339f4dac3ac176a24b49c45046a59fa
|
||||
git checkout 29af8408afad3da36824bd7912562202023ae924
|
||||
```
|
||||
|
||||
### 2.2.2 Build FlexRIC
|
||||
@@ -124,8 +124,10 @@ At the moment, the following measurements are supported in OAI RAN:
|
||||
* "RRU.PrbTotDl"
|
||||
* "RRU.PrbTotUl"
|
||||
|
||||
2. RC v01.03 (`xapp_kpm_rc`)
|
||||
At the moment, OAI RAN supports the RAN control function "QoS flow mapping configuration", i.e. creating a new DRB.
|
||||
2. RC v01.03
|
||||
Currently available RC xApps:
|
||||
* `xapp_kpm_rc` - RAN control function "QoS flow mapping configuration" support, i.e. creating a new DRB.
|
||||
* `xapp_rc_moni` - aperiodic subscription support for "UE RRC State Change"
|
||||
|
||||
3. MAC + RLC + PDCP + GTP (`xapp_gtp_mac_rlc_pdcp_moni`)
|
||||
|
||||
@@ -172,13 +174,25 @@ cd flexric
|
||||
./build/examples/ric/nearRT-RIC
|
||||
```
|
||||
|
||||
* start the KPM xApp
|
||||
* start the KPM monitor xApp
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_kpm_moni
|
||||
```
|
||||
|
||||
* start the (MAC + RLC + PDCP + GTP) xApp
|
||||
* start the RC monitor xApp
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_rc_moni
|
||||
```
|
||||
|
||||
* start the RC control xApp
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/kpm_rc/xapp_kpm_rc
|
||||
```
|
||||
|
||||
* start the (MAC + RLC + PDCP + GTP) monitor xApp
|
||||
```bash
|
||||
cd flexric
|
||||
./build/examples/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni
|
||||
|
||||
+1
-1
Submodule openair2/E2AP/flexric updated: 70dd779f53...29af8408af
@@ -809,7 +809,6 @@ void RCconfig_nr_prs(void)
|
||||
void RCconfig_NR_L1(void)
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
if (RC.gNB == NULL) {
|
||||
RC.gNB = (PHY_VARS_gNB **)malloc((1 + NUMBER_OF_gNB_MAX) * sizeof(PHY_VARS_gNB *));
|
||||
LOG_I(NR_PHY, "RC.gNB = %p\n", RC.gNB);
|
||||
|
||||
@@ -42,32 +42,6 @@
|
||||
#include "SCHED_NR/phy_frame_config_nr.h"
|
||||
#include "oai_asn1.h"
|
||||
|
||||
const long logicalChannelGroup0_NR = 0;
|
||||
typedef struct NR_LogicalChannelConfig__ul_SpecificParameters LcConfig_UlParamas_t;
|
||||
|
||||
const LcConfig_UlParamas_t NR_LCSRB1 = {
|
||||
.priority = 1,
|
||||
.prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity,
|
||||
.logicalChannelGroup = (long *)&logicalChannelGroup0_NR};
|
||||
|
||||
const LcConfig_UlParamas_t NR_LCSRB2 = {
|
||||
.priority = 3,
|
||||
.prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity,
|
||||
.logicalChannelGroup = (long *)&logicalChannelGroup0_NR};
|
||||
|
||||
const LcConfig_UlParamas_t NR_LCSRB3 = {
|
||||
.priority = 1,
|
||||
.prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity,
|
||||
.logicalChannelGroup = (long *)&logicalChannelGroup0_NR};
|
||||
|
||||
// these are the default values for SRB configurations(SRB1 and SRB2) as mentioned in 36.331 pg 258-259
|
||||
const NR_LogicalChannelConfig_t NR_SRB1_logicalChannelConfig_defaultValue = {.ul_SpecificParameters =
|
||||
(LcConfig_UlParamas_t *)&NR_LCSRB1};
|
||||
const NR_LogicalChannelConfig_t NR_SRB2_logicalChannelConfig_defaultValue = {.ul_SpecificParameters =
|
||||
(LcConfig_UlParamas_t *)&NR_LCSRB2};
|
||||
const NR_LogicalChannelConfig_t NR_SRB3_logicalChannelConfig_defaultValue = {.ul_SpecificParameters =
|
||||
(LcConfig_UlParamas_t *)&NR_LCSRB3};
|
||||
|
||||
void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table,
|
||||
int mu,
|
||||
NR_TDD_UL_DL_Pattern_t *pattern)
|
||||
@@ -132,11 +106,10 @@ void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table,
|
||||
|
||||
static void config_common_ue_sa(NR_UE_MAC_INST_t *mac,
|
||||
NR_ServingCellConfigCommonSIB_t *scc,
|
||||
module_id_t module_id,
|
||||
int cc_idP)
|
||||
{
|
||||
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
||||
mac->phy_config.Mod_id = module_id;
|
||||
mac->phy_config.Mod_id = mac->ue_id;
|
||||
mac->phy_config.CC_id = cc_idP;
|
||||
|
||||
LOG_D(MAC, "Entering SA UE Config Common\n");
|
||||
@@ -271,12 +244,11 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
static void config_common_ue(NR_UE_MAC_INST_t *mac,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
module_id_t module_id,
|
||||
int cc_idP)
|
||||
{
|
||||
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
||||
|
||||
mac->phy_config.Mod_id = module_id;
|
||||
mac->phy_config.Mod_id = mac->ue_id;
|
||||
mac->phy_config.CC_id = cc_idP;
|
||||
|
||||
// carrier config
|
||||
@@ -648,25 +620,13 @@ static void configure_ss_coreset(NR_BWP_PDCCH_t *pdcch, NR_PDCCH_Config_t *pdcch
|
||||
}
|
||||
}
|
||||
|
||||
static int lcid_cmp(const void *lc1, const void *lc2, void *mac_inst)
|
||||
static int lcid_cmp(const void *a, const void *b)
|
||||
{
|
||||
uint8_t id1 = ((nr_lcordered_info_t *)lc1)->lcids_ordered;
|
||||
uint8_t id2 = ((nr_lcordered_info_t *)lc2)->lcids_ordered;
|
||||
NR_UE_MAC_INST_t *mac = (NR_UE_MAC_INST_t *)mac_inst;
|
||||
|
||||
NR_LogicalChannelConfig_t **lc_config = &mac->logicalChannelConfig[0];
|
||||
|
||||
AssertFatal(id1 > 0 && id2 > 0, "undefined logical channel identity\n");
|
||||
AssertFatal(lc_config[id1 - 1] != NULL || lc_config[id2 - 1] != NULL, "logical channel configuration should be available\n");
|
||||
|
||||
return (lc_config[id1 - 1]->ul_SpecificParameters->priority - lc_config[id2 - 1]->ul_SpecificParameters->priority);
|
||||
}
|
||||
|
||||
void nr_release_mac_config_logicalChannelBearer(NR_UE_MAC_INST_t *mac, long channel_identity)
|
||||
{
|
||||
if (mac->logicalChannelConfig[channel_identity - 1] != NULL) {
|
||||
asn1cFreeStruc(asn_DEF_NR_LogicalChannelConfig, mac->logicalChannelConfig[channel_identity - 1]);
|
||||
}
|
||||
long priority_a = (*((nr_lcordered_info_t**)a))->priority;
|
||||
AssertFatal(priority_a > 0 && priority_a < 17, "Invalid priority value %ld\n", priority_a);
|
||||
long priority_b = (*((nr_lcordered_info_t**)b))->priority;
|
||||
AssertFatal(priority_b > 0 && priority_b < 17, "Invalid priority value %ld\n", priority_b);
|
||||
return priority_a - priority_b;
|
||||
}
|
||||
|
||||
static int nr_get_ms_bucketsizeduration(long bucketsizeduration)
|
||||
@@ -695,93 +655,111 @@ static int nr_get_ms_bucketsizeduration(long bucketsizeduration)
|
||||
}
|
||||
}
|
||||
|
||||
void nr_configure_mac_config_logicalChannelBearer(module_id_t module_id,
|
||||
long channel_identity,
|
||||
NR_LogicalChannelConfig_t *lc_config)
|
||||
static uint32_t get_lc_bucket_size(long prioritisedBitRate, long bucketSizeDuration)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
LOG_I(NR_MAC, "[MACLogicalChannelConfig]Applying RRC Logical Channel Config %d to lcid %li\n", module_id, channel_identity);
|
||||
mac->logicalChannelConfig[channel_identity - 1] = lc_config;
|
||||
|
||||
// initialize the variable Bj for every LCID
|
||||
mac->scheduling_info.lc_sched_info[channel_identity - 1].Bj = 0;
|
||||
|
||||
// store the bucket size
|
||||
int pbr = nr_get_pbr(lc_config->ul_SpecificParameters->prioritisedBitRate);
|
||||
int bsd = nr_get_ms_bucketsizeduration(lc_config->ul_SpecificParameters->bucketSizeDuration);
|
||||
|
||||
int pbr = nr_get_pbr(prioritisedBitRate);
|
||||
// in infinite pbr, the bucket is saturated by pbr
|
||||
if (lc_config->ul_SpecificParameters->prioritisedBitRate
|
||||
== NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) {
|
||||
int bsd = 0;
|
||||
if (prioritisedBitRate == NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity)
|
||||
bsd = 1;
|
||||
}
|
||||
mac->scheduling_info.lc_sched_info[channel_identity - 1].bucket_size = pbr * bsd;
|
||||
|
||||
if (lc_config->ul_SpecificParameters->logicalChannelGroup != NULL)
|
||||
mac->scheduling_info.lc_sched_info[channel_identity - 1].LCGID = *lc_config->ul_SpecificParameters->logicalChannelGroup;
|
||||
else
|
||||
mac->scheduling_info.lc_sched_info[channel_identity - 1].LCGID = 0;
|
||||
bsd = nr_get_ms_bucketsizeduration(bucketSizeDuration);
|
||||
|
||||
return pbr * bsd;
|
||||
}
|
||||
|
||||
static void configure_logicalChannelBearer(module_id_t module_id,
|
||||
// default configuration as per 38.331 section 9.2.1
|
||||
static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, NR_SRB_Identity_t srb_id)
|
||||
{
|
||||
lc_info->lcid = srb_id;
|
||||
lc_info->priority = srb_id == 2 ? 3 : 1;
|
||||
lc_info->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
|
||||
lc_info->bucket_size = get_lc_bucket_size(lc_info->prioritisedBitRate, 0);
|
||||
}
|
||||
|
||||
static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac,
|
||||
nr_lcordered_info_t *lc_info,
|
||||
NR_LogicalChannelConfig_t *mac_lc_config,
|
||||
NR_SRB_Identity_t srb_id)
|
||||
{
|
||||
if (srb_id > 0 && !mac_lc_config->ul_SpecificParameters) {
|
||||
// release configuration and reset to default
|
||||
set_default_logicalchannelconfig(lc_info, srb_id);
|
||||
mac->scheduling_info.lc_sched_info[lc_info->lcid - 1].LCGID = 0;
|
||||
return;
|
||||
}
|
||||
AssertFatal(mac_lc_config->ul_SpecificParameters, "UL parameters shouldn't be NULL for DRBs\n");
|
||||
struct NR_LogicalChannelConfig__ul_SpecificParameters *ul_parm = mac_lc_config->ul_SpecificParameters;
|
||||
lc_info->priority = ul_parm->priority;
|
||||
lc_info->prioritisedBitRate = ul_parm->prioritisedBitRate;
|
||||
// TODO Verify setting to 0 is ok, 331 just says need R (release if NULL)
|
||||
mac->scheduling_info.lc_sched_info[lc_info->lcid - 1].LCGID = ul_parm->logicalChannelGroup ? *ul_parm->logicalChannelGroup : 0;
|
||||
lc_info->bucket_size = get_lc_bucket_size(ul_parm->prioritisedBitRate, ul_parm->bucketSizeDuration);
|
||||
}
|
||||
|
||||
static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac,
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_toadd_list,
|
||||
struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_torelease_list)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
if (rlc_torelease_list) {
|
||||
for (int i = 0; i < rlc_torelease_list->list.count; i++) {
|
||||
if (rlc_torelease_list->list.array[i]) {
|
||||
int lc_identity = *rlc_torelease_list->list.array[i];
|
||||
nr_release_mac_config_logicalChannelBearer(mac, lc_identity);
|
||||
long id = *rlc_torelease_list->list.array[i];
|
||||
int j;
|
||||
for (j = 0; j < mac->lc_ordered_list.count; j++) {
|
||||
if (id == mac->lc_ordered_list.array[j]->lcid)
|
||||
break;
|
||||
}
|
||||
if (j < mac->lc_ordered_list.count) {
|
||||
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[j];
|
||||
asn_sequence_del(&mac->lc_ordered_list, j, 0);
|
||||
free(lc_info);
|
||||
}
|
||||
else
|
||||
LOG_E(NR_MAC, "Element not present in the list, impossible to release\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (rlc_toadd_list) {
|
||||
for (int i = 0; i < rlc_toadd_list->list.count; i++) {
|
||||
NR_RLC_BearerConfig_t *rlc_bearer = rlc_toadd_list->list.array[i];
|
||||
int lc_identity = rlc_bearer->logicalChannelIdentity;
|
||||
mac->lc_ordered_info[i].lcids_ordered = lc_identity;
|
||||
NR_LogicalChannelConfig_t *mac_lc_config = NULL;
|
||||
if (mac->logicalChannelConfig[lc_identity - 1] == NULL) {
|
||||
NR_LogicalChannelConfig_t *mac_lc_config = rlc_bearer->mac_LogicalChannelConfig;
|
||||
int j;
|
||||
for (j = 0; j < mac->lc_ordered_list.count; j++) {
|
||||
if (lc_identity == mac->lc_ordered_list.array[j]->lcid)
|
||||
break;
|
||||
}
|
||||
if (j < mac->lc_ordered_list.count) {
|
||||
LOG_D(NR_MAC, "Logical channel %d is already established, Reconfiguring now\n", lc_identity);
|
||||
if (mac_lc_config != NULL) {
|
||||
NR_SRB_Identity_t srb_id = 0;
|
||||
if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity)
|
||||
srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity;
|
||||
nr_configure_lc_config(mac, mac->lc_ordered_list.array[j], mac_lc_config, srb_id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* setup of new LCID*/
|
||||
nr_lcordered_info_t *lc_info = calloc(1, sizeof(*lc_info));
|
||||
lc_info->lcid = lc_identity;
|
||||
LOG_D(NR_MAC, "Establishing the logical channel %d\n", lc_identity);
|
||||
AssertFatal(rlc_bearer->servedRadioBearer, "servedRadioBearer should be present for LCID establishment\n");
|
||||
if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { /* SRB */
|
||||
NR_SRB_Identity_t srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity;
|
||||
if (rlc_bearer->mac_LogicalChannelConfig != NULL) {
|
||||
UPDATE_MAC_IE(mac_lc_config, rlc_bearer->mac_LogicalChannelConfig, NR_LogicalChannelConfig_t);
|
||||
} else {
|
||||
LOG_I(NR_RRC, "Applying the default logicalChannelConfig for SRB\n");
|
||||
if (srb_id == 1)
|
||||
mac_lc_config = (NR_LogicalChannelConfig_t *)&NR_SRB1_logicalChannelConfig_defaultValue;
|
||||
else if (srb_id == 2)
|
||||
mac_lc_config = (NR_LogicalChannelConfig_t *)&NR_SRB2_logicalChannelConfig_defaultValue;
|
||||
else if (srb_id == 3)
|
||||
mac_lc_config = (NR_LogicalChannelConfig_t *)&NR_SRB3_logicalChannelConfig_defaultValue;
|
||||
else
|
||||
AssertFatal(1 == 0, "The logical id %d is not a valid SRB id %li\n", lc_identity, srb_id);
|
||||
}
|
||||
if (mac_lc_config != NULL)
|
||||
nr_configure_lc_config(mac, lc_info, mac_lc_config, srb_id);
|
||||
else
|
||||
set_default_logicalchannelconfig(lc_info, srb_id);
|
||||
} else { /* DRB */
|
||||
AssertFatal(rlc_bearer->mac_LogicalChannelConfig,
|
||||
"When establishing a DRB, LogicalChannelConfig should be mandatorily present\n");
|
||||
UPDATE_MAC_IE(mac_lc_config, rlc_bearer->mac_LogicalChannelConfig, NR_LogicalChannelConfig_t);
|
||||
AssertFatal(mac_lc_config, "When establishing a DRB, LogicalChannelConfig should be mandatorily present\n");
|
||||
nr_configure_lc_config(mac, lc_info, mac_lc_config, 0);
|
||||
}
|
||||
} else {
|
||||
/* LC is already established, reconfiguring the LC */
|
||||
LOG_D(NR_MAC, "Logical channel %d is already established, Reconfiguring now\n", lc_identity);
|
||||
if (rlc_bearer->mac_LogicalChannelConfig != NULL) {
|
||||
UPDATE_MAC_IE(mac_lc_config, rlc_bearer->mac_LogicalChannelConfig, NR_LogicalChannelConfig_t);
|
||||
}
|
||||
}
|
||||
if (mac_lc_config) {
|
||||
mac->lc_ordered_info[i].logicalChannelConfig_ordered = mac_lc_config;
|
||||
nr_configure_mac_config_logicalChannelBearer(module_id, lc_identity, mac_lc_config);
|
||||
ASN_SEQUENCE_ADD(&mac->lc_ordered_list, lc_info);
|
||||
}
|
||||
}
|
||||
|
||||
// reorder the logical channels as per its priority
|
||||
qsort_r(mac->lc_ordered_info, rlc_toadd_list->list.count, sizeof(nr_lcordered_info_t), lcid_cmp, mac);
|
||||
qsort(mac->lc_ordered_list.array, mac->lc_ordered_list.count, sizeof(nr_lcordered_info_t*), lcid_cmp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,7 +805,7 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id,
|
||||
mac->get_sib1 = true;
|
||||
else if (sched_sib == 2)
|
||||
mac->get_otherSI = true;
|
||||
nr_ue_decode_mib(module_id, cc_idP);
|
||||
nr_ue_decode_mib(mac, cc_idP);
|
||||
}
|
||||
|
||||
static void setup_puschpowercontrol(NR_PUSCH_PowerControl_t *source, NR_PUSCH_PowerControl_t *target)
|
||||
@@ -1381,7 +1359,7 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id,
|
||||
reset_mac_inst(mac);
|
||||
reset_ra(&mac->ra);
|
||||
release_mac_configuration(mac);
|
||||
nr_ue_init_mac(module_id);
|
||||
nr_ue_init_mac(mac);
|
||||
|
||||
// Sending to PHY a request to resync
|
||||
// with no target cell ID
|
||||
@@ -1404,7 +1382,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
|
||||
UPDATE_MAC_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
|
||||
UPDATE_MAC_IE(mac->si_SchedulingInfo, si_SchedulingInfo, NR_SI_SchedulingInfo_t);
|
||||
|
||||
config_common_ue_sa(mac, scc, module_id, cc_idP);
|
||||
config_common_ue_sa(mac, scc, cc_idP);
|
||||
configure_common_BWP_dl(mac,
|
||||
0, // bwp-id
|
||||
&scc->downlinkConfigCommon.initialDownlinkBWP);
|
||||
@@ -1430,7 +1408,6 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id,
|
||||
}
|
||||
|
||||
static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
|
||||
module_id_t module_id,
|
||||
int cc_idP,
|
||||
const NR_ReconfigurationWithSync_t *reconfigurationWithSync)
|
||||
{
|
||||
@@ -1451,7 +1428,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
|
||||
mac->physCellId = *scc->physCellId;
|
||||
mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position;
|
||||
UPDATE_MAC_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t);
|
||||
config_common_ue(mac, scc, module_id, cc_idP);
|
||||
config_common_ue(mac, scc, cc_idP);
|
||||
if (scc->downlinkConfigCommon)
|
||||
configure_common_BWP_dl(mac,
|
||||
0, // bwp-id
|
||||
@@ -1467,7 +1444,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
|
||||
nr_ue_mac_default_configs(mac);
|
||||
|
||||
if (!get_softmodem_params()->emulate_l1) {
|
||||
mac->synch_request.Mod_id = module_id;
|
||||
mac->synch_request.Mod_id = mac->ue_id;
|
||||
mac->synch_request.CC_id = cc_idP;
|
||||
mac->synch_request.synch_req.target_Nid_cell = mac->physCellId;
|
||||
mac->if_module->synch_request(&mac->synch_request);
|
||||
@@ -1948,7 +1925,7 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
|
||||
mac->servCellIndex = spCellConfig->servCellIndex ? *spCellConfig->servCellIndex : 0;
|
||||
if (spCellConfig->reconfigurationWithSync) {
|
||||
LOG_A(NR_MAC, "Received reconfigurationWithSync\n");
|
||||
handle_reconfiguration_with_sync(mac, module_id, cc_idP, spCellConfig->reconfigurationWithSync);
|
||||
handle_reconfiguration_with_sync(mac, cc_idP, spCellConfig->reconfigurationWithSync);
|
||||
}
|
||||
if (scd) {
|
||||
configure_servingcell_info(&mac->sc_info, scd);
|
||||
@@ -1956,7 +1933,7 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
|
||||
}
|
||||
}
|
||||
|
||||
configure_logicalChannelBearer(module_id,
|
||||
configure_logicalChannelBearer(mac,
|
||||
cell_group_config->rlc_BearerToAddModList,
|
||||
cell_group_config->rlc_BearerToReleaseList);
|
||||
|
||||
|
||||
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
|
||||
#include "NR_SidelinkPreconfigNR-r16.h"
|
||||
#include "mac_proto.h"
|
||||
|
||||
void sl_ue_mac_free(uint8_t module_id)
|
||||
{
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
sl_nr_phy_config_request_t *sl_config =
|
||||
&mac->SL_MAC_PARAMS->sl_phy_config.sl_config_req;
|
||||
|
||||
uint8_t syncsource = sl_config->sl_sync_source.sync_source;
|
||||
|
||||
//Allocated by MAC only in case of SYNC_REF_UE
|
||||
//else it is freed as part of RRC pre-config structure
|
||||
if (syncsource == SL_SYNC_SOURCE_SYNC_REF_UE) {
|
||||
ASN_STRUCT_FREE (asn_DEF_NR_TDD_UL_DL_Pattern, mac->SL_MAC_PARAMS->sl_TDD_config);
|
||||
}
|
||||
|
||||
fapi_nr_max_tdd_periodicity_t *tdd_list =
|
||||
sl_config->tdd_table.max_tdd_periodicity_list;
|
||||
|
||||
// @todo: maybe this should be done by phy
|
||||
if (tdd_list) {
|
||||
int mu = sl_config->sl_bwp_config.sl_scs;
|
||||
int nb_slots_to_set = TDD_CONFIG_NB_FRAMES*(1<<mu)*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
for (int i=0; i<nb_slots_to_set; i++) {
|
||||
free_and_zero(tdd_list[i].max_num_of_symbol_per_slot_list);
|
||||
}
|
||||
free_and_zero(sl_config->tdd_table.max_tdd_periodicity_list);
|
||||
}
|
||||
|
||||
for (int i=0;i<SL_NR_MAC_NUM_RX_RESOURCE_POOLS;i++) {
|
||||
free_and_zero(mac->SL_MAC_PARAMS->sl_RxPool[i]);
|
||||
}
|
||||
for (int i=0;i<SL_NR_MAC_NUM_TX_RESOURCE_POOLS;i++) {
|
||||
free_and_zero(mac->SL_MAC_PARAMS->sl_TxPool[i]);
|
||||
}
|
||||
|
||||
free_and_zero(mac->SL_MAC_PARAMS);
|
||||
}
|
||||
|
||||
void sl_set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table,
|
||||
int mu,
|
||||
NR_TDD_UL_DL_Pattern_t *pattern)
|
||||
{
|
||||
const int nrofUplinkSlots = pattern->nrofUplinkSlots;
|
||||
const int nrofUplinkSymbols = pattern->nrofUplinkSymbols;
|
||||
const int nb_periods_per_frame = get_nb_periods_per_frame(pattern->dl_UL_TransmissionPeriodicity);
|
||||
const int nb_slots_per_period = ((1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) / nb_periods_per_frame;
|
||||
tdd_table->tdd_period_in_slots = nb_slots_per_period;
|
||||
|
||||
LOG_I(PHY,"UL slots:%d, symbols:%d, slots_per_period:%d\n",
|
||||
nrofUplinkSlots, nrofUplinkSymbols, nb_slots_per_period);
|
||||
|
||||
tdd_table->max_tdd_periodicity_list = (fapi_nr_max_tdd_periodicity_t *) malloc(nb_slots_per_period * sizeof(fapi_nr_max_tdd_periodicity_t));
|
||||
|
||||
for(int memory_alloc = 0 ; memory_alloc < nb_slots_per_period; memory_alloc++)
|
||||
tdd_table->max_tdd_periodicity_list[memory_alloc].max_num_of_symbol_per_slot_list =
|
||||
(fapi_nr_max_num_of_symbol_per_slot_t *) malloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT*sizeof(fapi_nr_max_num_of_symbol_per_slot_t));
|
||||
|
||||
int slot_number = (nb_slots_per_period - nrofUplinkSlots) - (nrofUplinkSymbols ? 1 : 0);
|
||||
if (nrofUplinkSymbols != 0) {
|
||||
for(int number_of_symbol = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; number_of_symbol < NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config = 1;
|
||||
}
|
||||
slot_number++;
|
||||
}
|
||||
while(slot_number < nb_slots_per_period) {
|
||||
for (int number_of_symbol = 0; number_of_symbol < nrofUplinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) {
|
||||
tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol%NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config = 1;
|
||||
if((number_of_symbol + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0)
|
||||
slot_number++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Prepares the PHY config to be sent to PHY. Prepares from the Valus from MAC context.
|
||||
static void sl_prepare_phy_config(int module_id,
|
||||
sl_nr_phy_config_request_t *phycfg,
|
||||
NR_SL_FreqConfigCommon_r16_t *freqcfg,
|
||||
uint8_t sync_source,
|
||||
uint32_t sl_OffsetDFN,
|
||||
NR_TDD_UL_DL_ConfigCommon_t *sl_TDD_config)
|
||||
{
|
||||
|
||||
|
||||
phycfg->sl_sync_source.sync_source = sync_source;
|
||||
LOG_I(NR_MAC, "Sidelink CFG: sync source:%d\n", phycfg->sl_sync_source.sync_source);
|
||||
|
||||
uint32_t pointA_ARFCN = freqcfg->sl_AbsoluteFrequencyPointA_r16;
|
||||
AssertFatal(pointA_ARFCN, "sl_AbsoluteFrequencyPointA_r16 cannot be 0\n");
|
||||
|
||||
int sl_band = 0;
|
||||
//REL 16 3GPP spec 38.101 section 5.2E.1 specifies 2 bands for operation on PC5 interface.
|
||||
//Band 47, Band 38
|
||||
if (pointA_ARFCN >= 790334 && pointA_ARFCN <= 795000)
|
||||
sl_band = 47;
|
||||
else if (pointA_ARFCN >= 514000 && pointA_ARFCN <= 524000)
|
||||
sl_band = 38;
|
||||
|
||||
AssertFatal(sl_band, "not valid band for Sidelink operation\n");
|
||||
|
||||
uint32_t SSB_ARFCN = (freqcfg->sl_AbsoluteFrequencySSB_r16)
|
||||
? *freqcfg->sl_AbsoluteFrequencySSB_r16 : 0;
|
||||
|
||||
AssertFatal(SSB_ARFCN, "sl_AbsoluteFrequencySSB cannot be 0\n");
|
||||
|
||||
LOG_I(NR_MAC, "SIDELINK CONFIGs: AbsFreqSSB:%d, AbsFreqPointA:%d, SL band:%d\n",
|
||||
SSB_ARFCN,pointA_ARFCN, sl_band);
|
||||
|
||||
//FREQSHIFT_7P5KHZ is DISABLED
|
||||
phycfg->sl_carrier_config.sl_frequency_shift_7p5khz = 0;
|
||||
phycfg->sl_carrier_config.sl_value_N = freqcfg->valueN_r16;
|
||||
|
||||
NR_SCS_SpecificCarrier_t *carriercfg =
|
||||
freqcfg->sl_SCS_SpecificCarrierList_r16.list.array[0];
|
||||
|
||||
AssertFatal(carriercfg, "SCS_SpecificCarrier cannot be NULL");
|
||||
|
||||
int bw_index = get_supported_band_index(carriercfg->subcarrierSpacing,
|
||||
sl_band,
|
||||
carriercfg->carrierBandwidth);
|
||||
phycfg->sl_carrier_config.sl_bandwidth = get_supported_bw_mhz(FR1, bw_index);
|
||||
|
||||
phycfg->sl_carrier_config.sl_frequency =
|
||||
from_nrarfcn(sl_band,carriercfg->subcarrierSpacing,pointA_ARFCN); // freq in kHz
|
||||
|
||||
phycfg->sl_carrier_config.sl_grid_size = carriercfg->carrierBandwidth;
|
||||
//For sidelink offset to carrier is 0. hence not used
|
||||
//phycfg->sl_carrier_config.sl_k0 = carriercfg->offsetToCarrier;
|
||||
|
||||
NR_SL_BWP_Generic_r16_t *bwp_generic = NULL;
|
||||
if (freqcfg->sl_BWP_List_r16 &&
|
||||
freqcfg->sl_BWP_List_r16->list.array[0] &&
|
||||
freqcfg->sl_BWP_List_r16->list.array[0]->sl_BWP_Generic_r16)
|
||||
bwp_generic = freqcfg->sl_BWP_List_r16->list.array[0]->sl_BWP_Generic_r16;
|
||||
|
||||
AssertFatal(bwp_generic, "SL-BWP Generic cannot be NULL");
|
||||
|
||||
NR_BWP_t *sl_bwp = bwp_generic->sl_BWP_r16;
|
||||
AssertFatal(sl_bwp, "SL-BWP cannot be NULL");
|
||||
|
||||
int locbw = bwp_generic->sl_BWP_r16->locationAndBandwidth;
|
||||
phycfg->sl_bwp_config.sl_bwp_size = NRRIV2BW(locbw, MAX_BWP_SIZE);
|
||||
phycfg->sl_bwp_config.sl_bwp_start = NRRIV2PRBOFFSET(locbw, MAX_BWP_SIZE);
|
||||
phycfg->sl_bwp_config.sl_scs = sl_bwp->subcarrierSpacing;
|
||||
|
||||
|
||||
int scs_scaling = 1<<(phycfg->sl_bwp_config.sl_scs);
|
||||
|
||||
if (pointA_ARFCN < 600000)
|
||||
scs_scaling = scs_scaling*3;
|
||||
if (pointA_ARFCN > 2016666)
|
||||
scs_scaling = scs_scaling>>2;
|
||||
//SSB arfcn points to middle RE of PSBCH 11 RBs
|
||||
uint32_t diff = (SSB_ARFCN - 66*scs_scaling) - pointA_ARFCN;
|
||||
//the RE offset from pointA where SSB starts
|
||||
phycfg->sl_bwp_config.sl_ssb_offset_point_a = diff/scs_scaling;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("diff:%d, scaling:%d, pointa:%d, ssb:%d\n", diff, scs_scaling, pointA_ARFCN, SSB_ARFCN);
|
||||
#endif
|
||||
|
||||
phycfg->sl_bwp_config.sl_dc_location = (bwp_generic->sl_TxDirectCurrentLocation_r16) ?
|
||||
*bwp_generic->sl_TxDirectCurrentLocation_r16 : 0;
|
||||
|
||||
const uint8_t values[] = {7,8,9,10,11,12,13,14};
|
||||
phycfg->sl_bwp_config.sl_num_symbols = (bwp_generic->sl_LengthSymbols_r16) ?
|
||||
values[*bwp_generic->sl_LengthSymbols_r16] : 0;
|
||||
|
||||
phycfg->sl_bwp_config.sl_start_symbol = (bwp_generic->sl_StartSymbol_r16) ?
|
||||
*bwp_generic->sl_StartSymbol_r16 : 0;
|
||||
|
||||
//0-EXTENDED, 1-NORMAL CP
|
||||
phycfg->sl_bwp_config.sl_cyclic_prefix = (sl_bwp->cyclicPrefix) ? EXTENDED : NORMAL;
|
||||
|
||||
AssertFatal(phycfg->sl_bwp_config.sl_cyclic_prefix == NORMAL, "Only NORMAL-CP Supported. Ext CP not yet supported\n");
|
||||
|
||||
|
||||
AssertFatal(phycfg->sl_bwp_config.sl_start_symbol >= 0 && phycfg->sl_bwp_config.sl_start_symbol <=7,
|
||||
"Sidelink Start symbol should be in range 0-7\n");
|
||||
|
||||
AssertFatal(phycfg->sl_bwp_config.sl_num_symbols >= 7 && phycfg->sl_bwp_config.sl_num_symbols <=14,
|
||||
"Num Sidelink symbols should be in range 7-14\n");
|
||||
|
||||
AssertFatal((phycfg->sl_bwp_config.sl_start_symbol + phycfg->sl_bwp_config.sl_num_symbols) <= 14,
|
||||
"Incorrect configuration of Start and num SL symbols\n");
|
||||
|
||||
//Configure PHY with TDD config only if the sync source is known.
|
||||
if (sync_source == SL_SYNC_SOURCE_LOCAL_TIMING ||
|
||||
sync_source == SL_SYNC_SOURCE_GNSS) {
|
||||
|
||||
phycfg->config_mask = 0xF;//Total config is sent
|
||||
phycfg->sl_sync_source.gnss_dfn_offset = sl_OffsetDFN;
|
||||
|
||||
// TDD Table Configuration
|
||||
sl_set_tdd_config_nr_ue(&phycfg->tdd_table,
|
||||
phycfg->sl_bwp_config.sl_scs,
|
||||
&sl_TDD_config->pattern1);
|
||||
|
||||
LOG_I(NR_MAC, "SIDELINK CONFIGs: tdd config period:%ld, mu:%ld, DLslots:%ld,ULslots:%ld Mixedslotsym DL:UL %ld:%ld\n",
|
||||
sl_TDD_config->pattern1.dl_UL_TransmissionPeriodicity, sl_TDD_config->referenceSubcarrierSpacing,
|
||||
sl_TDD_config->pattern1.nrofDownlinkSlots, sl_TDD_config->pattern1.nrofUplinkSlots,
|
||||
sl_TDD_config->pattern1.nrofDownlinkSymbols,sl_TDD_config->pattern1.nrofUplinkSymbols);
|
||||
|
||||
} else if (sync_source == SL_SYNC_SOURCE_NONE) {
|
||||
//Only Carrier config, BWP config sent
|
||||
phycfg->config_mask = 0x9;//partial config is sent
|
||||
}
|
||||
|
||||
//#ifdef SL_DEBUG
|
||||
char str[5][20] = {"NONE","GNBENB","GNSS","SYNC_REF_UE","LOCAL_TIMING"};
|
||||
LOG_I(NR_MAC, "UE[%d] Function %s - Phy config preparation:\n",module_id, __FUNCTION__);
|
||||
LOG_I(NR_MAC, "UE[%d] Sync source params: sync_source :%d-%s, gnss_dfn_offset:%d, rx_slss_id:%d\n",
|
||||
module_id,phycfg->sl_sync_source.sync_source,
|
||||
str[phycfg->sl_sync_source.sync_source],
|
||||
phycfg->sl_sync_source.gnss_dfn_offset,
|
||||
phycfg->sl_sync_source.rx_slss_id);
|
||||
LOG_I(NR_MAC, "UE[%d] Carrier CFG Params: freq:%ld, bw:%d, gridsize:%d, valueN:%d\n",
|
||||
module_id,phycfg->sl_carrier_config.sl_frequency,
|
||||
phycfg->sl_carrier_config.sl_bandwidth,
|
||||
phycfg->sl_carrier_config.sl_grid_size,
|
||||
phycfg->sl_carrier_config.sl_value_N);
|
||||
LOG_I(NR_MAC, "UE[%d] SL-BWP Params: start:%d, size:%d, scs:%d, Ncp:%d, startsym:%d, numsym:%d,ssb_offset:%d,dcloc:%d\n",
|
||||
module_id,phycfg->sl_bwp_config.sl_bwp_start,
|
||||
phycfg->sl_bwp_config.sl_bwp_size,
|
||||
phycfg->sl_bwp_config.sl_scs,
|
||||
phycfg->sl_bwp_config.sl_cyclic_prefix,
|
||||
phycfg->sl_bwp_config.sl_start_symbol,
|
||||
phycfg->sl_bwp_config.sl_num_symbols,
|
||||
phycfg->sl_bwp_config.sl_ssb_offset_point_a,
|
||||
phycfg->sl_bwp_config.sl_dc_location);
|
||||
|
||||
//#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// RRC calls this API when RRC is configured with Sidelink PRE-configuration I.E
|
||||
int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfiguration,
|
||||
uint8_t sync_source)
|
||||
{
|
||||
|
||||
LOG_I(NR_MAC,"[UE%d] SL RRC->MAC CONFIG RECEIVED. Syncsource:%d\n",
|
||||
module_id, sync_source);
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
AssertFatal(sl_preconfiguration !=NULL,"SL-Preconfig Cannot be NULL");
|
||||
AssertFatal(mac, "mac should have an instance");
|
||||
|
||||
if (!mac->SL_MAC_PARAMS)
|
||||
mac->SL_MAC_PARAMS = CALLOC(1, sizeof(sl_nr_ue_mac_params_t));
|
||||
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
|
||||
NR_SidelinkPreconfigNR_r16_t *sl_preconfig = &sl_preconfiguration->sidelinkPreconfigNR_r16;
|
||||
|
||||
//Only one entry supported in rel16.
|
||||
//Carrier freq config used for Sidelink
|
||||
|
||||
NR_SL_FreqConfigCommon_r16_t *freqcfg = (sl_preconfig->sl_PreconfigFreqInfoList_r16)
|
||||
? sl_preconfig->sl_PreconfigFreqInfoList_r16->list.array[0]
|
||||
: NULL;
|
||||
|
||||
AssertFatal(freqcfg !=NULL,"SL fcfg Cannot be NULL");
|
||||
|
||||
//MAx num of consecutive HARQ DTX before triggering RLF.
|
||||
const uint8_t MaxNumConsecutiveDTX[] = {1,2,3,4,6,8,16,32};
|
||||
sl_mac->sl_MaxNumConsecutiveDTX = (sl_preconfig->sl_MaxNumConsecutiveDTX_r16)
|
||||
? MaxNumConsecutiveDTX[*sl_preconfig->sl_MaxNumConsecutiveDTX_r16]
|
||||
: 0;
|
||||
|
||||
//priority of SL-SSB tx and rx
|
||||
sl_mac->sl_SSB_PriorityNR = (sl_preconfig->sl_SSB_PriorityNR_r16)
|
||||
? *sl_preconfig->sl_SSB_PriorityNR_r16 : 0;
|
||||
|
||||
//Indicates if CSI Reporting is enabled in UNICAST. is 0-ENABLED, 1-DISABLED
|
||||
sl_mac->sl_CSI_Acquisition = (sl_preconfig->sl_CSI_Acquisition_r16) ? 0 : 1;
|
||||
|
||||
//Used for DFN calculation in case Sync source = GNSS.
|
||||
uint32_t sl_OffsetDFN = (sl_preconfig->sl_OffsetDFN_r16)
|
||||
? *sl_preconfig->sl_OffsetDFN_r16 : 0;
|
||||
|
||||
NR_SL_BWP_ConfigCommon_r16_t *bwp = NULL;
|
||||
if (freqcfg->sl_BWP_List_r16 &&
|
||||
freqcfg->sl_BWP_List_r16->list.array[0])
|
||||
bwp = freqcfg->sl_BWP_List_r16->list.array[0];
|
||||
|
||||
AssertFatal(bwp!=NULL, "BWP config common cannot be NULL\n");
|
||||
if (bwp->sl_BWP_PoolConfigCommon_r16) {
|
||||
if (bwp->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16) {
|
||||
|
||||
for (int i=0;i<bwp->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16->list.count;i++) {
|
||||
NR_SL_ResourcePool_r16_t *rxpool = bwp->sl_BWP_PoolConfigCommon_r16->sl_RxPool_r16->list.array[i];
|
||||
if (rxpool) {
|
||||
if (sl_mac->sl_RxPool[i] == NULL)
|
||||
sl_mac->sl_RxPool[i] = malloc16_clear(sizeof(SL_ResourcePool_params_t));
|
||||
sl_mac->sl_RxPool[i]->respool = rxpool;
|
||||
uint16_t sci_1a_len = 0, num_subch = 0;
|
||||
sci_1a_len = sl_determine_sci_1a_len(&num_subch,
|
||||
sl_mac->sl_RxPool[i]->respool,
|
||||
&sl_mac->sl_RxPool[i]->sci_1a);
|
||||
sl_mac->sl_RxPool[i]->num_subch = num_subch;
|
||||
sl_mac->sl_RxPool[i]->sci_1a_len = sci_1a_len;
|
||||
|
||||
LOG_I(NR_MAC,"Rxpool[%d] - num subchannels:%d, sci_1a_len:%d\n",i,
|
||||
sl_mac->sl_RxPool[i]->num_subch,
|
||||
sl_mac->sl_RxPool[i]->sci_1a_len);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16) {
|
||||
|
||||
for (int i=0;i<bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16->list.count;i++) {
|
||||
|
||||
NR_SL_ResourcePool_r16_t *txpool =
|
||||
bwp->sl_BWP_PoolConfigCommon_r16->sl_TxPoolSelectedNormal_r16->list.array[0]->sl_ResourcePool_r16;
|
||||
|
||||
if (txpool) {
|
||||
if (sl_mac->sl_TxPool[i] == NULL)
|
||||
sl_mac->sl_TxPool[i] = malloc16_clear(sizeof(SL_ResourcePool_params_t));
|
||||
sl_mac->sl_TxPool[i]->respool = txpool;
|
||||
|
||||
uint16_t sci_1a_len = 0, num_subch = 0;
|
||||
sci_1a_len = sl_determine_sci_1a_len(&num_subch,
|
||||
sl_mac->sl_TxPool[i]->respool,
|
||||
&sl_mac->sl_TxPool[i]->sci_1a);
|
||||
|
||||
sl_mac->sl_TxPool[i]->num_subch = num_subch;
|
||||
sl_mac->sl_TxPool[i]->sci_1a_len = sci_1a_len;
|
||||
|
||||
LOG_I(NR_MAC,"Txpool[%d] - num subchannels:%d, sci_1a_len:%d\n",i,
|
||||
sl_mac->sl_TxPool[i]->num_subch,
|
||||
sl_mac->sl_TxPool[i]->sci_1a_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sync_source == SL_SYNC_SOURCE_GNSS ||
|
||||
sync_source == SL_SYNC_SOURCE_LOCAL_TIMING) {
|
||||
|
||||
NR_TDD_UL_DL_ConfigCommon_t *tdd_uldl_config = NULL;
|
||||
if (sl_preconfig->sl_PreconfigGeneral_r16 &&
|
||||
sl_preconfig->sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16)
|
||||
tdd_uldl_config = sl_preconfig->sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16;
|
||||
|
||||
AssertFatal((tdd_uldl_config!=NULL), "Sidelink MAC CFG: TDD Config cannot be NULL");
|
||||
AssertFatal((tdd_uldl_config->pattern2 == NULL), "Sidelink MAC CFG: pattern2 not yet supported");
|
||||
|
||||
sl_mac->sl_TDD_config = sl_preconfig->sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16;
|
||||
}
|
||||
|
||||
//Do not copy TDD config yet as SYNC source is not yet found
|
||||
if (sync_source == SL_SYNC_SOURCE_NONE) {
|
||||
if (sl_mac->sl_TDD_config)
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_TDD_UL_DL_ConfigCommon, sl_mac->sl_TDD_config);
|
||||
sl_mac->sl_TDD_config = NULL;
|
||||
}
|
||||
|
||||
nr_sl_phy_config_t *sl_phy_cfg = &sl_mac->sl_phy_config;
|
||||
sl_phy_cfg->Mod_id = module_id;
|
||||
sl_phy_cfg->CC_id = 0;
|
||||
|
||||
sl_prepare_phy_config(module_id, &sl_phy_cfg->sl_config_req,
|
||||
freqcfg, sync_source, sl_OffsetDFN, sl_mac->sl_TDD_config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//Copies the values of SSB time allocation from ASN format to MAC context
|
||||
static void sl_mac_config_ssb_time_alloc(uint8_t module_id,
|
||||
NR_SL_SSB_TimeAllocation_r16_t *sl_SSB_TimeAllocation_r16,
|
||||
sl_ssb_timealloc_t *ssb_time_alloc)
|
||||
{
|
||||
|
||||
const uint8_t values[] = {1,2,4,8,16,32,64};
|
||||
ssb_time_alloc->sl_NumSSB_WithinPeriod =
|
||||
(sl_SSB_TimeAllocation_r16->sl_NumSSB_WithinPeriod_r16 != NULL)
|
||||
? values[*sl_SSB_TimeAllocation_r16->sl_NumSSB_WithinPeriod_r16] : 0;
|
||||
ssb_time_alloc->sl_TimeOffsetSSB = (sl_SSB_TimeAllocation_r16->sl_TimeOffsetSSB_r16 != NULL)
|
||||
? *sl_SSB_TimeAllocation_r16->sl_TimeOffsetSSB_r16 : 0;
|
||||
ssb_time_alloc->sl_TimeInterval = (sl_SSB_TimeAllocation_r16->sl_TimeInterval_r16 != NULL)
|
||||
? *sl_SSB_TimeAllocation_r16->sl_TimeInterval_r16 : 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//This API is called by RRC after it determines that UE needs to transmit SL-SSB
|
||||
// SLSS id and SL-MIB is given to MAC by RRC
|
||||
void nr_rrc_mac_transmit_slss_req(module_id_t module_id,
|
||||
uint8_t *sl_mib_payload,
|
||||
uint16_t tx_slss_id,
|
||||
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta)
|
||||
{
|
||||
|
||||
sl_nr_ue_mac_params_t *sl_mac = get_mac_inst(module_id)->SL_MAC_PARAMS;
|
||||
AssertFatal(sl_mac,"sidelink MAC cannot be NULL");
|
||||
AssertFatal(tx_slss_id < 672,"SLSS id cannot be >= 672. id:%d", tx_slss_id);
|
||||
AssertFatal(ssb_ta,"ssb_ta cannot be NULL");
|
||||
|
||||
sl_mac->tx_sl_bch.slss_id = tx_slss_id;
|
||||
sl_mac->tx_sl_bch.status = 1;
|
||||
memcpy(sl_mac->tx_sl_bch.sl_mib,sl_mib_payload, 4);
|
||||
|
||||
sl_mac->tx_sl_bch.num_ssb = 0;
|
||||
sl_mac->tx_sl_bch.ssb_slot = 0;
|
||||
|
||||
sl_mac_config_ssb_time_alloc(module_id,
|
||||
ssb_ta,
|
||||
&sl_mac->tx_sl_bch.ssb_time_alloc);
|
||||
|
||||
LOG_I(NR_MAC,"[UE%d]SL RRC->MAC: TX SLSS REQ SLSS-id:%d, SL-MIB:%x, numssb:%d, offset:%d, interval:%d\n",
|
||||
module_id, sl_mac->tx_sl_bch.slss_id,
|
||||
*((uint32_t *)sl_mib_payload),
|
||||
sl_mac->tx_sl_bch.ssb_time_alloc.sl_NumSSB_WithinPeriod,
|
||||
sl_mac->tx_sl_bch.ssb_time_alloc.sl_TimeOffsetSSB,
|
||||
sl_mac->tx_sl_bch.ssb_time_alloc.sl_TimeInterval);
|
||||
|
||||
uint8_t byte0 = 0;
|
||||
uint8_t byte1 = 0;
|
||||
sl_nr_bwp_config_t *cfg = &sl_mac->sl_phy_config.sl_config_req.sl_bwp_config;
|
||||
sl_prepare_psbch_payload(sl_mac->sl_TDD_config, &byte0, &byte1,
|
||||
cfg->sl_scs,cfg->sl_num_symbols,cfg->sl_start_symbol);
|
||||
|
||||
sl_mac->tx_sl_bch.sl_mib[0] = byte0;
|
||||
sl_mac->tx_sl_bch.sl_mib[1] = byte1 | sl_mac->tx_sl_bch.sl_mib[1];
|
||||
|
||||
LOG_I(NR_MAC, "[UE%d]SL RRC->MAC: TX SLSS REQ - TDD CONFIG STUFFED INSIDE - SL-MIB :%x\n",
|
||||
module_id, *((uint32_t *)sl_mac->tx_sl_bch.sl_mib));
|
||||
}
|
||||
|
||||
//This API is called by RRC after it determines that UE needs to keep
|
||||
// receiving SL-SSB from the sync ref UE
|
||||
void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
|
||||
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta,
|
||||
uint16_t rx_slss_id,
|
||||
uint8_t *sl_mib)
|
||||
{
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
sl_nr_ue_mac_params_t *sl_mac = mac->SL_MAC_PARAMS;
|
||||
AssertFatal(sl_mac,"Sidelink MAC instance cannot be NULL");
|
||||
|
||||
AssertFatal(ssb_ta,"ssb_ta cannot be NULL");
|
||||
AssertFatal(rx_slss_id < 672,"SLSS id cannot be >= 672. id:%d", rx_slss_id);
|
||||
AssertFatal(sl_mib,"sl_mib cannot be NULL");
|
||||
|
||||
sl_nr_phy_config_request_t *sl_config = &sl_mac->sl_phy_config.sl_config_req;
|
||||
|
||||
//Update configs if Sync source is not set else nothing to be done
|
||||
if ( sl_config->sl_sync_source.sync_source == SL_SYNC_SOURCE_NONE) {
|
||||
//Set SYNC source as SYNC REF UE and send the remaining config to PHY
|
||||
sl_config->config_mask = 0xF;//all configs done.
|
||||
sl_config->sl_sync_source.sync_source = SL_SYNC_SOURCE_SYNC_REF_UE;
|
||||
sl_config->sl_sync_source.rx_slss_id = rx_slss_id;
|
||||
|
||||
|
||||
sl_mac->rx_sl_bch.status = 1;
|
||||
sl_mac->rx_sl_bch.slss_id = rx_slss_id;
|
||||
|
||||
sl_mac->rx_sl_bch.num_ssb = 0;
|
||||
sl_mac->rx_sl_bch.ssb_slot = 0;
|
||||
|
||||
sl_mac_config_ssb_time_alloc(module_id,
|
||||
ssb_ta,
|
||||
&sl_mac->rx_sl_bch.ssb_time_alloc);
|
||||
|
||||
LOG_I(NR_MAC,"[UE%d]SL RRC->MAC: RX SLSS REQ SLSS-id:%d, SL-MIB:%x, numssb:%d, offset:%d, interval:%d\n",
|
||||
module_id, sl_mac->rx_sl_bch.slss_id,
|
||||
*((uint32_t *)sl_mib),
|
||||
sl_mac->rx_sl_bch.ssb_time_alloc.sl_NumSSB_WithinPeriod,
|
||||
sl_mac->rx_sl_bch.ssb_time_alloc.sl_TimeOffsetSSB,
|
||||
sl_mac->rx_sl_bch.ssb_time_alloc.sl_TimeInterval);
|
||||
|
||||
if (sl_mac->sl_TDD_config == NULL)
|
||||
sl_mac->sl_TDD_config = CALLOC(sizeof(NR_TDD_UL_DL_ConfigCommon_t), 1);
|
||||
|
||||
sl_nr_phy_config_request_t *cfg = &sl_mac->sl_phy_config.sl_config_req;
|
||||
int ret = 1;
|
||||
ret = sl_decode_sl_TDD_Config(sl_mac->sl_TDD_config,
|
||||
sl_mib[0], sl_mib[1]&0xF0,
|
||||
cfg->sl_bwp_config.sl_scs,
|
||||
cfg->sl_bwp_config.sl_num_symbols,
|
||||
cfg->sl_bwp_config.sl_start_symbol);
|
||||
|
||||
if (ret == 0) {
|
||||
//sl_tdd_config bytes are all 1's - no TDD config present use all slots for sidelink.
|
||||
//Spec not clear -- TBD...
|
||||
sl_mac->sl_TDD_config->pattern1.nrofUplinkSlots =
|
||||
NR_NUMBER_OF_SUBFRAMES_PER_FRAME*(1<<cfg->sl_bwp_config.sl_scs);
|
||||
}
|
||||
|
||||
sl_set_tdd_config_nr_ue(&cfg->tdd_table,
|
||||
cfg->sl_bwp_config.sl_scs,
|
||||
&sl_mac->sl_TDD_config->pattern1);
|
||||
LOG_I(MAC, "SIDELINK CONFIGs: tdd config period:%ld, mu:%ld, DLslots:%ld,ULslots:%ld Mixedslotsym DL:UL %ld:%ld\n",
|
||||
sl_mac->sl_TDD_config->pattern1.dl_UL_TransmissionPeriodicity,sl_mac->sl_TDD_config->referenceSubcarrierSpacing,
|
||||
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSlots, sl_mac->sl_TDD_config->pattern1.nrofUplinkSlots,
|
||||
sl_mac->sl_TDD_config->pattern1.nrofDownlinkSymbols,sl_mac->sl_TDD_config->pattern1.nrofUplinkSymbols);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
|
||||
#include "LAYER2/MAC/mac.h"
|
||||
#include "NR_MAC_COMMON/nr_mac_extern.h"
|
||||
#include "mac_defs_sl.h"
|
||||
|
||||
/* RRC */
|
||||
#include "NR_DRX-Config.h"
|
||||
@@ -181,12 +182,10 @@ typedef struct {
|
||||
int32_t LCID_buffer_remain;
|
||||
// buffer status for each lcid
|
||||
uint8_t LCID_status;
|
||||
// Bj bucket usage per lcid
|
||||
// logical channel group id of this LCID
|
||||
long LCGID;
|
||||
// Bj bucket usage per lcid
|
||||
int32_t Bj;
|
||||
// Bucket size per lcid
|
||||
int32_t bucket_size;
|
||||
// logical channel group id for each LCID
|
||||
uint8_t LCGID;
|
||||
} NR_LC_SCHEDULING_INFO;
|
||||
|
||||
typedef struct {
|
||||
@@ -317,9 +316,11 @@ typedef struct {
|
||||
/// Received TPC command (in dB) from RAR
|
||||
int8_t Msg3_TPC;
|
||||
/// Flag to indicate whether it is the first Msg3 to be transmitted
|
||||
uint8_t first_Msg3;
|
||||
bool first_Msg3;
|
||||
/// RA Msg3 size in bytes
|
||||
uint8_t Msg3_size;
|
||||
/// Msg3 buffer
|
||||
uint8_t *Msg3_buffer;
|
||||
|
||||
/// Random-access Contention Resolution Timer active flag
|
||||
uint8_t RA_contention_resolution_timer_active;
|
||||
@@ -434,10 +435,11 @@ typedef struct ssb_list_info {
|
||||
|
||||
typedef struct nr_lcordered_info_s {
|
||||
// logical channels ids ordered as per priority
|
||||
int lcids_ordered;
|
||||
|
||||
// logical channel configurations reordered as per priority
|
||||
NR_LogicalChannelConfig_t *logicalChannelConfig_ordered;
|
||||
NR_LogicalChannelIdentity_t lcid;
|
||||
long priority;
|
||||
long prioritisedBitRate;
|
||||
// Bucket size per lcid
|
||||
uint32_t bucket_size;
|
||||
} nr_lcordered_info_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -482,10 +484,6 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
bool phy_config_request_sent;
|
||||
frame_type_t frame_type;
|
||||
|
||||
/* PDUs */
|
||||
/// Outgoing CCCH pdu for PHY
|
||||
CCCH_PDU CCCH_pdu;
|
||||
|
||||
/* Random Access */
|
||||
/// CRNTI
|
||||
uint16_t crnti;
|
||||
@@ -513,11 +511,9 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
/// BSR report flag management
|
||||
uint8_t BSR_reporting_active;
|
||||
|
||||
// Pointers to LogicalChannelConfig indexed by LogicalChannelIdentity. Note NULL means LCHAN is inactive.
|
||||
NR_LogicalChannelConfig_t *logicalChannelConfig[NR_MAX_NUM_LCID];
|
||||
|
||||
// order lc info
|
||||
nr_lcordered_info_t lc_ordered_info[NR_MAX_NUM_LCID];
|
||||
A_SEQUENCE_OF(nr_lcordered_info_t) lc_ordered_list;
|
||||
|
||||
NR_UE_SCHEDULING_INFO scheduling_info;
|
||||
|
||||
/// PHR
|
||||
@@ -548,6 +544,9 @@ typedef struct NR_UE_MAC_INST_s {
|
||||
|
||||
pthread_mutex_t mutex_dl_info;
|
||||
|
||||
//SIDELINK MAC PARAMETERS
|
||||
sl_nr_ue_mac_params_t *SL_MAC_PARAMS;
|
||||
|
||||
} NR_UE_MAC_INST_t;
|
||||
|
||||
/*@}*/
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __MAC_DEFS_SL_H__
|
||||
#define __MAC_DEFS_SL_H__
|
||||
|
||||
#include "sidelink_nr_ue_interface.h"
|
||||
#include "NR_SL-ResourcePool-r16.h"
|
||||
#include "NR_TDD-UL-DL-ConfigCommon.h"
|
||||
#include "NR_MAC_COMMON/nr_mac.h"
|
||||
#include "NR_UE_PHY_INTERFACE/NR_IF_Module.h"
|
||||
|
||||
#define SL_NR_MAC_NUM_RX_RESOURCE_POOLS 1
|
||||
#define SL_NR_MAC_NUM_TX_RESOURCE_POOLS 1
|
||||
#define SL_NUM_BYTES_TIMERESOURCEBITMAP 20
|
||||
|
||||
// Size of Fixed fields prio (3), sci_2ndstage(2),
|
||||
// betaoffsetindicator(2), num dmrs ports (1), mcs (5bits)
|
||||
#define SL_SCI_FORMAT_1A_LEN_IN_BITS_FIXED_FIELDS 13
|
||||
|
||||
#define NR_SBCCH_SL_BCH 0xFF
|
||||
|
||||
#define sci_field_t dci_field_t
|
||||
|
||||
typedef struct sidelink_sci_format_1a_fields {
|
||||
|
||||
// Priority of this transmission
|
||||
uint8_t priority; //3 bits
|
||||
//Indicates the format to be used in 2nd stage i.e SCI format 2 sent on PSSCH
|
||||
//00 - SCI FORMAT 2A, 01 - SCI FORMAT 2B, 10, 11 - Reserved
|
||||
//Spec 38.212 Table 8.3.1.1-1
|
||||
uint8_t sci_format_2nd_stage; //2 bits
|
||||
//Num modulated symbols for stage 2 SCI - TBD:
|
||||
// Spec 38.212 Table 8.3.1.1-2
|
||||
uint8_t beta_offset_indicator; //2 bits
|
||||
//determine the number of layers for data on PSSCH
|
||||
// Spec 38.212 Table 8.3.1.1-3
|
||||
uint8_t num_dmrs_ports; //1 bit
|
||||
//Modulation and coding scheme to be used for data on PSSCH
|
||||
uint8_t mcs; //5 bits
|
||||
|
||||
//Identifies the frequence resource (subchannels) to be used for PSSCH/PSCCH
|
||||
//sl-MaxNumPerReserve is 2 - ceil(log2(N_subch*(N_subch+1)/2)) bits
|
||||
//sl-MaxNumPerReserve is 3 - ceil(log2(N_subch*(N_subch+1)(2*N_subch+1)/6)) bits
|
||||
sci_field_t frequency_resource_assignment; //variable
|
||||
//Identifies the Time resource (slots) to be used for PSSCH/PSCCH
|
||||
//sl-MaxNumPerReserve is 2 - 5 bits
|
||||
//sl-MaxNumPerReserve is 3 - 9 bits
|
||||
sci_field_t time_resource_assignment; //variable
|
||||
//TBD:
|
||||
//sl-MultiReserveResource is not configured - 0 bits
|
||||
//sl-MultiReserveResource is configured - ceil(log2(number of entries in sl-ResourceReservePeriodList)) bits
|
||||
sci_field_t resource_reservation_period; //variable
|
||||
//Identifies the DMRS Pattern to be used on PSSCH
|
||||
//ceil(log2(number of dmrs patterns in sl-PSSCH-DMRS-TimePatternList)) bits
|
||||
sci_field_t dmrs_pattern; //variable
|
||||
//Identifies the TABLE to be used to determine MCS on PSSCH
|
||||
//1 table configured in sl-Additional-MCS-Table - 1 bit
|
||||
//2 tables configured in sl-Additional-MCS-Table - 2 bits
|
||||
//Not configured- 0 bits
|
||||
sci_field_t additional_mcs_table_indicator; //variable
|
||||
//Identifies the number of symbols for PSFCH
|
||||
//sl-PSFCH-Period Not configured- 0 bits
|
||||
//if sl-PSFCH-Period configured and value 2 or 4 - 1 bit
|
||||
sci_field_t psfch_overhead_indication; //variable
|
||||
//number of bits determined by sl-NumReservedbits
|
||||
//Value encoded is 0
|
||||
sci_field_t reserved_bits;
|
||||
|
||||
} sidelink_sci_format_1a_fields_t;
|
||||
|
||||
typedef struct SL_ResourcePool_params {
|
||||
|
||||
//This holds the structure from RRC
|
||||
NR_SL_ResourcePool_r16_t *respool;
|
||||
|
||||
//NUM Subchannels in this resource pool
|
||||
uint16_t num_subch;
|
||||
|
||||
//SCI-1A length is the same for this resource pool.
|
||||
uint16_t sci_1a_len;
|
||||
|
||||
//SCI-1A configuration according to RESPOOL configured.
|
||||
sidelink_sci_format_1a_fields_t sci_1a;
|
||||
|
||||
} SL_ResourcePool_params_t;
|
||||
|
||||
typedef struct sl_ssb_timealloc {
|
||||
|
||||
uint32_t sl_NumSSB_WithinPeriod;
|
||||
uint32_t sl_TimeOffsetSSB;
|
||||
uint32_t sl_TimeInterval;
|
||||
|
||||
} sl_ssb_timealloc_t;
|
||||
|
||||
typedef struct sl_bch_params {
|
||||
|
||||
//configured from RRC
|
||||
//Parameters used to determine PSBCH slot
|
||||
sl_ssb_timealloc_t ssb_time_alloc;
|
||||
uint16_t slss_id;
|
||||
bool status;
|
||||
uint8_t sl_mib[4];
|
||||
|
||||
//Parameters incremented by MAC PSBCH scheduler
|
||||
//after every SSB txn/reception
|
||||
uint16_t num_ssb;
|
||||
uint16_t ssb_slot;
|
||||
|
||||
} sl_bch_params_t;
|
||||
|
||||
typedef struct sl_nr_ue_mac_params {
|
||||
|
||||
//Holds the RX resource pool from RRC and its related parameters
|
||||
SL_ResourcePool_params_t *sl_RxPool[SL_NR_MAC_NUM_RX_RESOURCE_POOLS];
|
||||
//Holds the TX resource pool from RRC and its related parameters
|
||||
SL_ResourcePool_params_t *sl_TxPool[SL_NR_MAC_NUM_TX_RESOURCE_POOLS];
|
||||
|
||||
//Holds either the TDD config from RRC
|
||||
//or TDD config decoded from SL-MIB
|
||||
NR_TDD_UL_DL_ConfigCommon_t *sl_TDD_config;
|
||||
|
||||
//Configured from RRC
|
||||
uint32_t sl_MaxNumConsecutiveDTX;
|
||||
uint32_t sl_SSB_PriorityNR;
|
||||
uint8_t sl_CSI_Acquisition;
|
||||
|
||||
//MAC prepares this and sends it to PHY
|
||||
nr_sl_phy_config_t sl_phy_config;
|
||||
|
||||
//Holds Broadcast params incase UE sends Sidelink SSB
|
||||
sl_bch_params_t tx_sl_bch;
|
||||
//Holds Broadcast params incase UE receives SL-SSB
|
||||
sl_bch_params_t rx_sl_bch;
|
||||
|
||||
} sl_nr_ue_mac_params_t;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -146,8 +146,8 @@
|
||||
} while (0)
|
||||
|
||||
/**\brief initialize the field in nr_mac instance
|
||||
\param module_id module id */
|
||||
void nr_ue_init_mac(module_id_t module_idP);
|
||||
\param mac MAC pointer */
|
||||
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data);
|
||||
|
||||
@@ -155,18 +155,18 @@ void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data
|
||||
\param mac mac instance */
|
||||
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
void nr_ue_decode_mib(module_id_t module_id, int cc_id);
|
||||
void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id);
|
||||
|
||||
void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch);
|
||||
|
||||
/**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind
|
||||
\param module_id module id
|
||||
\param mac pointer to MAC instance
|
||||
\param cc_id component carrier id
|
||||
\param gNB_index gNB index
|
||||
\param sibs_mask sibs mask
|
||||
\param pduP pointer to pdu
|
||||
\param pdu_length length of pdu */
|
||||
int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id,
|
||||
int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint8_t ack_nack,
|
||||
@@ -208,26 +208,26 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac);
|
||||
performs BSR/SR/PHR procedures, random access procedure handler and DLSCH/ULSCH procedures.
|
||||
\param dl_info DL indication
|
||||
\param ul_info UL indication*/
|
||||
void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info);
|
||||
void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info);
|
||||
void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info);
|
||||
void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info);
|
||||
|
||||
/*! \fn int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slotP);
|
||||
/*! \fn int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP);
|
||||
\brief Called by PHY to get sdu for PUSCH transmission. It performs the following operations: Checks BSR for DCCH, DCCH1 and
|
||||
DTCH corresponding to previous values computed either in SR or BSR procedures. It gets rlc status indications on DCCH,DCCH1 and
|
||||
DTCH and forms BSR elements and PHR in MAC header. CRNTI element is not supported yet. It computes transport block for up to 3
|
||||
SDUs and generates header and forms the complete MAC SDU. \param[in] module_idP Instance id of UE in machine \param[in] frameP
|
||||
SDUs and generates header and forms the complete MAC SDU. \param[in] mac pointer to MAC instance \param[in] frameP
|
||||
subframe number \param[in] slotP slot number
|
||||
*/
|
||||
int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slotP);
|
||||
int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP);
|
||||
|
||||
/*! \fn nr_update_bsr
|
||||
\brief get the rlc stats and update the bsr level for each lcid
|
||||
\param[in] module_idP instance of the UE
|
||||
\param[in] mac pointer to UE MAC instance
|
||||
\param[in] frameP Frame index
|
||||
\param[in] slotP number
|
||||
\param[in] gNB_index
|
||||
*/
|
||||
bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index);
|
||||
bool nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index);
|
||||
|
||||
/*! \fn nr_locate_BsrIndexByBufferSize (int *table, int size, int value)
|
||||
\brief locate the BSR level in the table as defined in 38.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table.
|
||||
@@ -239,12 +239,12 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
|
||||
uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size,
|
||||
int value);
|
||||
|
||||
/*! \fn int nr_get_pbr(uint8_t prioritizedbitrate)
|
||||
/*! \fn int nr_get_pbr(long prioritizedbitrate)
|
||||
\brief get the rate in kbps from the rate configured by the higher layer
|
||||
\param[in] prioritizedbitrate
|
||||
\return the rate in kbps
|
||||
*/
|
||||
uint32_t nr_get_pbr(uint8_t prioritizedbitrate);
|
||||
uint32_t nr_get_pbr(long prioritizedbitrate);
|
||||
|
||||
/*! \fn int nr_get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer)
|
||||
\brief get the number of subframe from the periodic BSR timer configured by the higher layers
|
||||
@@ -260,14 +260,19 @@ int nr_get_sf_periodicBSRTimer(uint8_t bucketSize);
|
||||
*/
|
||||
int nr_get_sf_retxBSRTimer(uint8_t retxBSR_Timer);
|
||||
|
||||
int8_t nr_ue_process_dci(module_id_t module_id,
|
||||
int8_t nr_ue_process_dci(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
dci_pdu_rel15_t *dci,
|
||||
fapi_nr_dci_indication_pdu_t *dci_ind);
|
||||
int nr_ue_process_dci_indication_pdu(module_id_t module_id, int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci);
|
||||
int8_t nr_ue_process_csirs_measurements(module_id_t module_id,
|
||||
int nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
int gNB_index,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
fapi_nr_dci_indication_pdu_t *dci);
|
||||
int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
fapi_nr_csirs_measurements_t *csirs_measurements);
|
||||
@@ -312,11 +317,9 @@ uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp);
|
||||
@param pdu_id index of DL PDU
|
||||
@returns void
|
||||
*/
|
||||
void nr_ue_send_sdu(nr_downlink_indication_t *dl_info,
|
||||
int pdu_id);
|
||||
void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id);
|
||||
|
||||
void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
int pdu_id);
|
||||
void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac,nr_downlink_indication_t *dl_info, int pdu_id);
|
||||
|
||||
int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
|
||||
NR_UE_MAC_INST_t *mac,
|
||||
@@ -334,7 +337,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac,
|
||||
|
||||
void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, const frame_t frame, const int slot);
|
||||
|
||||
uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframe,
|
||||
@@ -388,12 +391,12 @@ int nr_get_Pcmax(NR_UE_MAC_INST_t *mac, int Qm, bool powerBoostPi2BPSK, int scs,
|
||||
|
||||
/* \brief This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211 tables 6.3.3.2.x
|
||||
and fills the PRACH PDU per each FD occasion.
|
||||
@param module_idP Index of UE instance
|
||||
@param mac pointer to MAC instance
|
||||
@param frameP Frame index
|
||||
@param slotP Slot index
|
||||
@returns void
|
||||
*/
|
||||
void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, void *phy_data);
|
||||
void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP, void *phy_data);
|
||||
void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot);
|
||||
void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot);
|
||||
void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment);
|
||||
@@ -409,11 +412,11 @@ void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac,
|
||||
sub_frame_t current_slot,
|
||||
uint8_t Msg3_tda_id);
|
||||
|
||||
void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources);
|
||||
void nr_ue_contention_resolution(NR_UE_MAC_INST_t *mac, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources);
|
||||
|
||||
void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot);
|
||||
void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot);
|
||||
|
||||
void nr_ra_succeeded(const module_id_t mod_id, const uint8_t gNB_index, const frame_t frame, const int slot);
|
||||
void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot);
|
||||
|
||||
void nr_get_RA_window(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
@@ -428,19 +431,15 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4
|
||||
@param gNB_id gNB index
|
||||
@param nr_slot_tx slot for PRACH transmission
|
||||
@returns indication to generate PRACH to phy */
|
||||
uint8_t nr_ue_get_rach(module_id_t mod_id,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
uint8_t gNB_id,
|
||||
int nr_slot_tx);
|
||||
void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx);
|
||||
|
||||
/* \brief Function implementing the routine for the selection of Random Access resources (5.1.2 TS 38.321).
|
||||
@param module_idP Index of UE instance
|
||||
@param mac pointer to MAC instance
|
||||
@param CC_id Component Carrier Index
|
||||
@param gNB_index gNB index
|
||||
@param rach_ConfigDedicated
|
||||
@returns void */
|
||||
void nr_get_prach_resources(module_id_t mod_id,
|
||||
void nr_get_prach_resources(NR_UE_MAC_INST_t *mac,
|
||||
int CC_id,
|
||||
uint8_t gNB_id,
|
||||
NR_PRACH_RESOURCES_t *prach_resources,
|
||||
@@ -449,22 +448,19 @@ void nr_get_prach_resources(module_id_t mod_id,
|
||||
void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack);
|
||||
void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind);
|
||||
|
||||
void init_RA(module_id_t mod_id,
|
||||
void init_RA(NR_UE_MAC_INST_t *mac,
|
||||
NR_PRACH_RESOURCES_t *prach_resources,
|
||||
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon,
|
||||
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric,
|
||||
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated);
|
||||
|
||||
int16_t get_prach_tx_power(module_id_t mod_id);
|
||||
int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac);
|
||||
|
||||
void set_ra_rnti(NR_UE_MAC_INST_t *mac, fapi_nr_ul_config_prach_pdu *prach_pdu);
|
||||
|
||||
void nr_Msg1_transmitted(module_id_t mod_id);
|
||||
|
||||
void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id);
|
||||
void nr_get_msg3_payload(module_id_t mod_id, uint8_t *buf, int TBS_max);
|
||||
|
||||
void nr_ue_msg2_scheduler(module_id_t mod_id, uint16_t rach_frame, uint16_t rach_slot, uint16_t *msg2_frame, uint16_t *msg2_slot);
|
||||
void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac);
|
||||
void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id);
|
||||
void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max);
|
||||
|
||||
int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu,
|
||||
fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu,
|
||||
@@ -519,4 +515,28 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
|
||||
RAR_grant_t *rar_grant,
|
||||
uint16_t rnti,
|
||||
const nr_dci_format_t dci_format);
|
||||
|
||||
int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfiguration,
|
||||
uint8_t sync_source);
|
||||
|
||||
void nr_rrc_mac_transmit_slss_req(module_id_t module_id,
|
||||
uint8_t *sl_mib_payload,
|
||||
uint16_t tx_slss_id,
|
||||
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta);
|
||||
void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
|
||||
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta,
|
||||
uint16_t rx_slss_id,
|
||||
uint8_t *sl_mib);
|
||||
void sl_prepare_psbch_payload(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
|
||||
uint8_t *bits_0_to_7, uint8_t *bits_8_to_11,
|
||||
uint8_t mu, uint8_t L, uint8_t Y);
|
||||
|
||||
uint8_t sl_decode_sl_TDD_Config(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
|
||||
uint8_t bits_0_to_7, uint8_t bits_8_to_11,
|
||||
uint8_t mu, uint8_t L, uint8_t Y);
|
||||
|
||||
uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
|
||||
NR_SL_ResourcePool_r16_t *rpool,
|
||||
sidelink_sci_format_1a_fields_t *sci_1a);
|
||||
#endif
|
||||
|
||||
@@ -53,10 +53,9 @@ void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, message_p);
|
||||
}
|
||||
|
||||
void nr_ue_init_mac(module_id_t module_idP)
|
||||
void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
LOG_I(NR_MAC, "[UE%d] Applying default macMainConfig\n", module_idP);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
LOG_I(NR_MAC, "[UE%d] Initializing MAC\n", mac->ue_id);
|
||||
mac->first_sync_frame = -1;
|
||||
mac->get_sib1 = false;
|
||||
mac->get_otherSI = false;
|
||||
@@ -99,11 +98,9 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
|
||||
|
||||
for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
|
||||
LOG_D(NR_MAC, "Applying default logical channel config for LCGID %d\n", i);
|
||||
mac->scheduling_info.lc_sched_info[i].Bj = -1;
|
||||
mac->scheduling_info.lc_sched_info[i].bucket_size = -1;
|
||||
mac->scheduling_info.lc_sched_info[i].LCGID = 0; // defaults to 0 irrespective of SRB or DRB
|
||||
mac->scheduling_info.lc_sched_info[i].LCID_status = LCID_EMPTY;
|
||||
mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0;
|
||||
mac->scheduling_info.lc_sched_info[i].Bj = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,9 +111,9 @@ NR_UE_MAC_INST_t *nr_l2_init_ue(int nb_inst)
|
||||
AssertFatal(nr_ue_mac_inst, "Couldn't allocate %d instances of MAC module\n", nb_inst);
|
||||
|
||||
for (int j = 0; j < nb_inst; j++) {
|
||||
nr_ue_init_mac(j);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(j);
|
||||
mac->ue_id = j;
|
||||
nr_ue_init_mac(mac);
|
||||
nr_ue_mac_default_configs(mac);
|
||||
if (get_softmodem_params()->sa)
|
||||
ue_init_config_request(mac, get_softmodem_params()->numerology);
|
||||
@@ -136,6 +133,7 @@ NR_UE_MAC_INST_t *get_mac_inst(module_id_t module_id)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = &nr_ue_mac_inst[(int)module_id];
|
||||
AssertFatal(mac, "Couldn't get MAC inst %d\n", module_id);
|
||||
AssertFatal(mac->ue_id == module_id, "MAC ID %d doesn't match with input %d\n", mac->ue_id, module_id);
|
||||
return mac;
|
||||
}
|
||||
|
||||
@@ -146,7 +144,8 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
|
||||
nr_ue_mac_default_configs(nr_mac);
|
||||
|
||||
// initialize Bj for each logical channel to zero
|
||||
// Done in default config but to -1 (is that correct?)
|
||||
for (int i = 0; i < NR_MAX_NUM_LCID; i++)
|
||||
nr_mac->scheduling_info.lc_sched_info[i].Bj = 0;
|
||||
|
||||
// stop all running timers
|
||||
// TODO
|
||||
@@ -166,7 +165,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
|
||||
// TODO not sure what needs to be done here
|
||||
|
||||
// flush Msg3 buffer
|
||||
// TODO we don't have a Msg3 buffer
|
||||
free_and_zero(nr_mac->ra.Msg3_buffer);
|
||||
|
||||
// cancel any triggered Scheduling Request procedure
|
||||
// Done in default config
|
||||
@@ -221,9 +220,10 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac)
|
||||
for (int i = 0; i < mac->ul_BWPs.count; i++)
|
||||
release_ul_BWP(mac, i);
|
||||
|
||||
for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
|
||||
nr_release_mac_config_logicalChannelBearer(mac, i + 1);
|
||||
memset(&mac->lc_ordered_info[i], 0, sizeof(nr_lcordered_info_t));
|
||||
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
|
||||
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
|
||||
asn_sequence_del(&mac->lc_ordered_list, i, 0);
|
||||
free(lc_info);
|
||||
}
|
||||
|
||||
memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
|
||||
|
||||
@@ -41,37 +41,34 @@
|
||||
#include <executables/softmodem-common.h>
|
||||
#include "openair2/LAYER2/RLC/rlc.h"
|
||||
|
||||
int16_t get_prach_tx_power(module_id_t mod_id) {
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
RA_config_t *ra = &mac->ra;
|
||||
int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm);
|
||||
int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER - pathloss + 30);
|
||||
return min(ra->prach_resources.RA_PCMAX, ra_preamble_rx_power);
|
||||
|
||||
}
|
||||
|
||||
// Random Access procedure initialization as per 5.1.1 and initialization of variables specific
|
||||
// to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16)
|
||||
// todo:
|
||||
// - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX (currently hardcoded to 0)
|
||||
void init_RA(module_id_t mod_id,
|
||||
void init_RA(NR_UE_MAC_INST_t *mac,
|
||||
NR_PRACH_RESOURCES_t *prach_resources,
|
||||
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon,
|
||||
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric,
|
||||
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
mac->state = UE_PERFORMING_RA;
|
||||
RA_config_t *ra = &mac->ra;
|
||||
ra->RA_active = 1;
|
||||
ra->ra_PreambleIndex = -1;
|
||||
ra->RA_usedGroupA = 1;
|
||||
ra->RA_RAPID_found = 0;
|
||||
ra->preambleTransMax = 0;
|
||||
ra->first_Msg3 = 1;
|
||||
RA_config_t *ra = &mac->ra;
|
||||
ra->RA_active = 1;
|
||||
ra->ra_PreambleIndex = -1;
|
||||
ra->RA_usedGroupA = 1;
|
||||
ra->RA_RAPID_found = 0;
|
||||
ra->preambleTransMax = 0;
|
||||
ra->first_Msg3 = true;
|
||||
ra->starting_preamble_nb = 0;
|
||||
ra->RA_backoff_cnt = 0;
|
||||
ra->RA_backoff_cnt = 0;
|
||||
ra->RA_window_cnt = -1;
|
||||
|
||||
fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
|
||||
@@ -94,21 +91,21 @@ void init_RA(module_id_t mod_id,
|
||||
ra->cfra = 1;
|
||||
} else if (rach_ConfigDedicated->ext1){
|
||||
if (rach_ConfigDedicated->ext1->cfra_TwoStep_r16){
|
||||
LOG_I(MAC, "In %s: setting RA type to 2-step...\n", __FUNCTION__);
|
||||
LOG_I(MAC, "Setting RA type to 2-step...\n");
|
||||
prach_resources->RA_TYPE = RA_2STEP;
|
||||
ra->cfra = 1;
|
||||
} else {
|
||||
LOG_E(MAC, "In %s: config not handled\n", __FUNCTION__);
|
||||
LOG_E(MAC, "Config not handled\n");
|
||||
}
|
||||
} else {
|
||||
LOG_E(MAC, "In %s: config not handled\n", __FUNCTION__);
|
||||
LOG_E(MAC, "Config not handled\n");
|
||||
}
|
||||
} else if (nr_rach_ConfigCommon){
|
||||
LOG_I(MAC, "Initialization of 4-step contention-based random access procedure\n");
|
||||
prach_resources->RA_TYPE = RA_4STEP;
|
||||
ra->cfra = 0;
|
||||
} else {
|
||||
LOG_E(MAC, "In %s: config not handled\n", __FUNCTION__);
|
||||
LOG_E(MAC, "Config not handled\n");
|
||||
}
|
||||
|
||||
switch (rach_ConfigGeneric->powerRampingStep){ // in dB
|
||||
@@ -164,15 +161,14 @@ void init_RA(module_id_t mod_id,
|
||||
|
||||
if (nr_rach_ConfigCommon->ext1) {
|
||||
if (nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity_r16){
|
||||
LOG_D(MAC, "In %s:%d: Missing implementation for Access Identity initialization procedures\n", __FUNCTION__, __LINE__);
|
||||
LOG_D(MAC, "Missing implementation for Access Identity initialization procedures\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */
|
||||
int8_t nr_get_DELTA_PREAMBLE(module_id_t mod_id, int CC_id, uint16_t prach_format)
|
||||
static int8_t nr_get_DELTA_PREAMBLE(NR_UE_MAC_INST_t *mac, int CC_id, uint16_t prach_format)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
|
||||
NR_SubcarrierSpacing_t scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing;
|
||||
int prach_sequence_length = nr_rach_ConfigCommon->prach_RootSequenceIndex.present - 1;
|
||||
@@ -260,7 +256,10 @@ int8_t nr_get_DELTA_PREAMBLE(module_id_t mod_id, int CC_id, uint16_t prach_forma
|
||||
return 5 + 3*mu;
|
||||
|
||||
default:
|
||||
AssertFatal(1 == 0, "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n", mod_id, prach_format, prachConfigIndex);
|
||||
AssertFatal(1 == 0, "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n",
|
||||
mac->ue_id,
|
||||
prach_format,
|
||||
prachConfigIndex);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -273,20 +272,21 @@ int8_t nr_get_DELTA_PREAMBLE(module_id_t mod_id, int CC_id, uint16_t prach_forma
|
||||
// - RA_PREAMBLE_POWER_RAMPING_STEP dB
|
||||
// - POWER_OFFSET_2STEP_RA dB
|
||||
// returns receivedTargerPower in dBm
|
||||
int nr_get_Po_NOMINAL_PUSCH(NR_PRACH_RESOURCES_t *prach_resources, module_id_t mod_id, uint8_t CC_id)
|
||||
static int nr_get_Po_NOMINAL_PUSCH(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources, uint8_t CC_id)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
int8_t receivedTargerPower;
|
||||
int8_t delta_preamble;
|
||||
|
||||
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
|
||||
long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower;
|
||||
delta_preamble = nr_get_DELTA_PREAMBLE(mod_id, CC_id, prach_resources->prach_format);
|
||||
delta_preamble = nr_get_DELTA_PREAMBLE(mac, CC_id, prach_resources->prach_format);
|
||||
|
||||
receivedTargerPower = preambleReceivedTargetPower + delta_preamble + (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP + prach_resources->POWER_OFFSET_2STEP_RA;
|
||||
|
||||
LOG_D(MAC, "In %s: receivedTargerPower is %d dBm \n", __FUNCTION__, receivedTargerPower);
|
||||
receivedTargerPower = preambleReceivedTargetPower +
|
||||
delta_preamble +
|
||||
(prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP +
|
||||
prach_resources->POWER_OFFSET_2STEP_RA;
|
||||
|
||||
LOG_D(MAC, "ReceivedTargerPower is %d dBm \n", receivedTargerPower);
|
||||
return receivedTargerPower;
|
||||
}
|
||||
|
||||
@@ -544,24 +544,25 @@ void set_ra_rnti(NR_UE_MAC_INST_t *mac, fapi_nr_ul_config_prach_pdu *prach_pdu){
|
||||
// - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission
|
||||
// - Contention-based RA preamble selection:
|
||||
// -- selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB
|
||||
void nr_get_prach_resources(module_id_t mod_id,
|
||||
void nr_get_prach_resources(NR_UE_MAC_INST_t *mac,
|
||||
int CC_id,
|
||||
uint8_t gNB_id,
|
||||
NR_PRACH_RESOURCES_t *prach_resources,
|
||||
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated){
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated)
|
||||
{
|
||||
RA_config_t *ra = &mac->ra;
|
||||
|
||||
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
|
||||
|
||||
LOG_D(MAC, "In %s: getting PRACH resources frame (first_Msg3 %d)\n", __FUNCTION__, ra->first_Msg3);
|
||||
LOG_D(MAC, "Getting PRACH resources frame (first_Msg3 %d)\n", ra->first_Msg3);
|
||||
|
||||
if (rach_ConfigDedicated) {
|
||||
if (rach_ConfigDedicated->cfra){
|
||||
uint8_t cfra_ssb_resource_idx = 0;
|
||||
ra->ra_PreambleIndex = rach_ConfigDedicated->cfra->resources.choice.ssb->ssb_ResourceList.list.array[cfra_ssb_resource_idx]->ra_PreambleIndex;
|
||||
LOG_D(MAC, "In %s: selected RA preamble index %d for contention-free random access procedure for SSB with Id %d\n", __FUNCTION__, ra->ra_PreambleIndex, cfra_ssb_resource_idx);
|
||||
LOG_D(MAC, "Selected RA preamble index %d for contention-free random access procedure for SSB with Id %d\n",
|
||||
ra->ra_PreambleIndex,
|
||||
cfra_ssb_resource_idx);
|
||||
}
|
||||
} else {
|
||||
/* TODO: This controls the tx_power of UE and the ramping procedure of RA of UE. Later we
|
||||
@@ -574,22 +575,20 @@ void nr_get_prach_resources(module_id_t mod_id,
|
||||
|
||||
if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER > 1)
|
||||
prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER++;
|
||||
prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id);
|
||||
prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id);
|
||||
|
||||
}
|
||||
|
||||
// TbD: RA_attempt_number not used
|
||||
void nr_Msg1_transmitted(module_id_t mod_id){
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
RA_config_t *ra = &mac->ra;
|
||||
ra->ra_state = WAIT_RAR;
|
||||
ra->RA_attempt_number++;
|
||||
}
|
||||
|
||||
void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id){
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id)
|
||||
{
|
||||
RA_config_t *ra = &mac->ra;
|
||||
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
|
||||
long mu = mac->current_UL_BWP->scs;
|
||||
@@ -601,25 +600,31 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, slot
|
||||
ra->RA_contention_resolution_target_frame = (frameP + (RA_contention_resolution_timer_subframes/10)) % MAX_FRAME_NUMBER;
|
||||
ra->RA_contention_resolution_target_slot = (slotP + (RA_contention_resolution_timer_subframes * subframes_per_slot)) % nr_slots_per_frame[mu];
|
||||
|
||||
LOG_D(MAC,"In %s: [UE %d] CB-RA: contention resolution timer set in frame.slot %d.%d and expiring in %d.%d\n",
|
||||
__FUNCTION__, mod_id, frameP, slotP, ra->RA_contention_resolution_target_frame, ra->RA_contention_resolution_target_slot);
|
||||
LOG_D(MAC,"[UE %d] CB-RA: contention resolution timer set in frame.slot %d.%d and expiring in %d.%d\n",
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
slotP,
|
||||
ra->RA_contention_resolution_target_frame,
|
||||
ra->RA_contention_resolution_target_slot);
|
||||
|
||||
ra->RA_contention_resolution_timer_active = 1;
|
||||
ra->ra_state = WAIT_CONTENTION_RESOLUTION;
|
||||
}
|
||||
|
||||
void nr_get_msg3_payload(module_id_t mod_id, uint8_t *buf, int TBS_max)
|
||||
void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
RA_config_t *ra = &mac->ra;
|
||||
|
||||
// we already stored MSG3 in the buffer, we can use that
|
||||
if (ra->Msg3_buffer) {
|
||||
buf = ra->Msg3_buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *pdu = buf;
|
||||
*(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_CCCH};
|
||||
pdu += sizeof(NR_MAC_SUBHEADER_FIXED);
|
||||
// here a big race condition: nothing ensure RRC thread has already pushed data to rlc
|
||||
// there is no issue inside RLC,
|
||||
// if RRC has called nr_rlc_srb_recv_sdu(),
|
||||
// we are good even if the name is misleading (we send a ssrb msg, not receive if)
|
||||
tbs_size_t len = mac_rlc_data_req(mod_id,
|
||||
tbs_size_t len = mac_rlc_data_req(mac->ue_id,
|
||||
mac->ue_id,
|
||||
0,
|
||||
0,
|
||||
@@ -644,6 +649,8 @@ void nr_get_msg3_payload(module_id_t mod_id, uint8_t *buf, int TBS_max)
|
||||
*(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_PADDING};
|
||||
pdu += sizeof(NR_MAC_SUBHEADER_FIXED);
|
||||
}
|
||||
ra->Msg3_buffer = calloc(TBS_max, sizeof(uint8_t));
|
||||
memcpy(ra->Msg3_buffer, buf, sizeof(uint8_t) * TBS_max);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -659,13 +666,8 @@ void nr_get_msg3_payload(module_id_t mod_id, uint8_t *buf, int TBS_max)
|
||||
* @gNB_id gNB ID
|
||||
* @nr_slot_tx current UL TX slot
|
||||
*/
|
||||
uint8_t nr_ue_get_rach(module_id_t mod_id,
|
||||
int CC_id,
|
||||
frame_t frame,
|
||||
uint8_t gNB_id,
|
||||
int nr_slot_tx)
|
||||
void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
RA_config_t *ra = &mac->ra;
|
||||
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated;
|
||||
NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources;
|
||||
@@ -677,32 +679,22 @@ uint8_t nr_ue_get_rach(module_id_t mod_id,
|
||||
ra->ra_state = GENERATE_PREAMBLE;
|
||||
} else {
|
||||
LOG_D(NR_MAC,"PRACH Condition not met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "In %s: [UE %d][%d.%d]: ra_state %d, RA_active %d\n",
|
||||
__FUNCTION__,
|
||||
mod_id,
|
||||
frame,
|
||||
nr_slot_tx,
|
||||
ra->ra_state,
|
||||
ra->RA_active);
|
||||
LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active);
|
||||
|
||||
if (ra->ra_state > RA_UE_IDLE && ra->ra_state < RA_SUCCEEDED) {
|
||||
|
||||
if (ra->RA_active == 0) {
|
||||
NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon;
|
||||
NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
|
||||
init_RA(mod_id, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated);
|
||||
init_RA(mac, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated);
|
||||
|
||||
LOG_D(NR_MAC, "In %s: RA not active. Checking for data to transmit from upper layers...\n", __FUNCTION__);
|
||||
|
||||
const uint8_t TBS_max = 8 + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); // Note: unclear the reason behind the selection of such TBS_max
|
||||
// TODO this piece of code is required to compute MSG3_size that is used by ra_preambles_config function
|
||||
// Not a good implementation, it needs improvements
|
||||
int size_sdu = 0;
|
||||
uint8_t mac_ce[16] = {0};
|
||||
uint8_t *pdu = get_softmodem_params()->sa ? mac->CCCH_pdu.payload : mac_ce;
|
||||
const uint8_t *payload = pdu;
|
||||
|
||||
// Concerning the C-RNTI MAC CE, it has to be included if the UL transmission (Msg3) is not being made for the CCCH logical channel.
|
||||
// Therefore it has been assumed that this event only occurs only when RA is done and it is not SA mode.
|
||||
@@ -729,35 +721,9 @@ uint8_t nr_ue_get_rach(module_id_t mod_id,
|
||||
}
|
||||
|
||||
} else if (!get_softmodem_params()->sa) {
|
||||
|
||||
size_sdu = nr_write_ce_ulsch_pdu(pdu, mac, 0, &(mac->crnti), NULL, NULL, NULL);
|
||||
pdu += size_sdu;
|
||||
uint8_t temp_pdu[16] = {0};
|
||||
size_sdu = nr_write_ce_ulsch_pdu(temp_pdu, mac, 0, &(mac->crnti), NULL, NULL, NULL);
|
||||
ra->Msg3_size = size_sdu;
|
||||
|
||||
}
|
||||
|
||||
if (size_sdu > 0 && (ra->ra_state == GENERATE_PREAMBLE || get_softmodem_params()->nsa)) {
|
||||
|
||||
LOG_D(NR_MAC, "[UE %d][%d.%d]: starting initialisation Random Access Procedure...\n", mod_id, frame, nr_slot_tx);
|
||||
|
||||
// Padding: fill remainder with 0
|
||||
if (TBS_max - ra->Msg3_size > 0) {
|
||||
AssertFatal(TBS_max > ra->Msg3_size, "In %s: allocated resources are not enough for Msg3!\n", __FUNCTION__);
|
||||
LOG_D(NR_MAC, "Remaining %d bytes, filling with padding\n",TBS_max - ra->Msg3_size);
|
||||
((NR_MAC_SUBHEADER_FIXED *) pdu)->R = 0;
|
||||
((NR_MAC_SUBHEADER_FIXED *) pdu)->LCID = UL_SCH_LCID_PADDING;
|
||||
pdu += sizeof(NR_MAC_SUBHEADER_FIXED);
|
||||
memset(pdu, 0, TBS_max - ra->Msg3_size - sizeof(NR_MAC_SUBHEADER_FIXED));
|
||||
}
|
||||
|
||||
// Dumping ULSCH payload
|
||||
LOG_D(NR_MAC, "Dumping UL Msg3 MAC PDU with length %d: \n", TBS_max);
|
||||
for(int k = 0; k < TBS_max; k++) {
|
||||
LOG_D(NR_MAC,"(%i): %i\n", k, payload[k]);
|
||||
}
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if (ra->RA_window_cnt != -1) { // RACH is active
|
||||
|
||||
@@ -773,42 +739,40 @@ uint8_t nr_ue_get_rach(module_id_t mod_id,
|
||||
|
||||
if(ra->cfra) {
|
||||
// Reset RA_active flag: it disables Msg3 retransmission (8.3 of TS 38.213)
|
||||
nr_ra_succeeded(mod_id, gNB_id, frame, nr_slot_tx);
|
||||
nr_ra_succeeded(mac, gNB_id, frame, nr_slot_tx);
|
||||
}
|
||||
|
||||
} else if (ra->RA_window_cnt == 0 && !ra->RA_RAPID_found) {
|
||||
|
||||
LOG_W(MAC, "[UE %d][%d:%d] RAR reception failed \n", mod_id, frame, nr_slot_tx);
|
||||
LOG_W(MAC, "[UE %d][%d:%d] RAR reception failed \n", mac->ue_id, frame, nr_slot_tx);
|
||||
|
||||
nr_ra_failed(mod_id, CC_id, prach_resources, frame, nr_slot_tx);
|
||||
nr_ra_failed(mac, CC_id, prach_resources, frame, nr_slot_tx);
|
||||
|
||||
} else if (ra->RA_window_cnt > 0) {
|
||||
|
||||
LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA window count %d) \n", mod_id, frame, nr_slot_tx, ra->RA_window_cnt);
|
||||
LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA window count %d) \n", mac->ue_id, frame, nr_slot_tx, ra->RA_window_cnt);
|
||||
|
||||
// Fill in preamble and PRACH resources
|
||||
ra->RA_window_cnt--;
|
||||
if (ra->ra_state == GENERATE_PREAMBLE) {
|
||||
nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, rach_ConfigDedicated);
|
||||
nr_get_prach_resources(mac, CC_id, gNB_id, prach_resources, rach_ConfigDedicated);
|
||||
}
|
||||
} else if (ra->RA_backoff_cnt > 0) {
|
||||
|
||||
LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA backoff count %d) \n", mod_id, frame, nr_slot_tx, ra->RA_backoff_cnt);
|
||||
LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA backoff count %d) \n", mac->ue_id, frame, nr_slot_tx, ra->RA_backoff_cnt);
|
||||
|
||||
ra->RA_backoff_cnt--;
|
||||
|
||||
if ((ra->RA_backoff_cnt > 0 && ra->ra_state == GENERATE_PREAMBLE) || ra->RA_backoff_cnt == 0) {
|
||||
nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, rach_ConfigDedicated);
|
||||
nr_get_prach_resources(mac, CC_id, gNB_id, prach_resources, rach_ConfigDedicated);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ra->RA_contention_resolution_timer_active) {
|
||||
nr_ue_contention_resolution(mod_id, CC_id, frame, nr_slot_tx, prach_resources);
|
||||
nr_ue_contention_resolution(mac, CC_id, frame, nr_slot_tx, prach_resources);
|
||||
}
|
||||
|
||||
return ra->ra_state;
|
||||
}
|
||||
|
||||
void nr_get_RA_window(NR_UE_MAC_INST_t *mac)
|
||||
@@ -858,9 +822,8 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac)
|
||||
// WIP todo:
|
||||
// - beam failure recovery
|
||||
// - RA completed
|
||||
void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources){
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
void nr_ue_contention_resolution(NR_UE_MAC_INST_t *mac, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources)
|
||||
{
|
||||
RA_config_t *ra = &mac->ra;
|
||||
|
||||
if (ra->RA_contention_resolution_timer_active == 1) {
|
||||
@@ -870,8 +833,8 @@ void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame
|
||||
ra->RA_active = 0;
|
||||
ra->RA_contention_resolution_timer_active = 0;
|
||||
// Signal PHY to quit RA procedure
|
||||
LOG_E(MAC, "[UE %d] CB-RA: Contention resolution timer has expired, RA procedure has failed...\n", module_id);
|
||||
nr_ra_failed(module_id, cc_id, prach_resources, frame, slot);
|
||||
LOG_E(MAC, "[UE %d] CB-RA: Contention resolution timer has expired, RA procedure has failed...\n", mac->ue_id);
|
||||
nr_ra_failed(mac, cc_id, prach_resources, frame, slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -880,36 +843,35 @@ void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame
|
||||
// according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16
|
||||
// todo:
|
||||
// - complete handling of received contention-based RA preamble
|
||||
void nr_ra_succeeded(const module_id_t mod_id, const uint8_t gNB_index, const frame_t frame, const int slot)
|
||||
void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
RA_config_t *ra = &mac->ra;
|
||||
|
||||
if (ra->cfra) {
|
||||
LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CF-RA: RAR successfully received.\n", mod_id, frame, slot);
|
||||
LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CF-RA: RAR successfully received.\n", mac->ue_id, frame, slot);
|
||||
ra->RA_window_cnt = -1;
|
||||
} else {
|
||||
LOG_A(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CB-RA: Contention Resolution is successful.\n", mod_id, frame, slot);
|
||||
LOG_A(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CB-RA: Contention Resolution is successful.\n", mac->ue_id, frame, slot);
|
||||
ra->RA_contention_resolution_timer_active = 0;
|
||||
mac->crnti = ra->t_crnti;
|
||||
ra->t_crnti = 0;
|
||||
LOG_D(MAC, "In %s: [UE %d][%d.%d] CB-RA: cleared contention resolution timer...\n", __FUNCTION__, mod_id, frame, slot);
|
||||
LOG_D(MAC, "[UE %d][%d.%d] CB-RA: cleared contention resolution timer...\n", mac->ue_id, frame, slot);
|
||||
}
|
||||
|
||||
LOG_D(MAC, "In %s: [UE %d] clearing RA_active flag...\n", __FUNCTION__, mod_id);
|
||||
LOG_D(MAC, "[UE %d] clearing RA_active flag...\n", mac->ue_id);
|
||||
ra->RA_active = 0;
|
||||
ra->ra_state = RA_SUCCEEDED;
|
||||
mac->state = UE_CONNECTED;
|
||||
nr_mac_rrc_ra_ind(mod_id, frame, true);
|
||||
free_and_zero(ra->Msg3_buffer);
|
||||
nr_mac_rrc_ra_ind(mac->ue_id, frame, true);
|
||||
}
|
||||
|
||||
// Handling failure of RA procedure @ MAC layer
|
||||
// according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16
|
||||
// todo:
|
||||
// - complete handling of received contention-based RA preamble
|
||||
void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot)
|
||||
void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
RA_config_t *ra = &mac->ra;
|
||||
// Random seed generation
|
||||
unsigned int seed;
|
||||
@@ -922,7 +884,7 @@ void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_res
|
||||
seed = (unsigned int) (rdtsc_oai() & ~0);
|
||||
}
|
||||
|
||||
ra->first_Msg3 = 1;
|
||||
ra->first_Msg3 = true;
|
||||
ra->ra_PreambleIndex = -1;
|
||||
ra->ra_state = RA_UE_IDLE;
|
||||
|
||||
@@ -930,13 +892,16 @@ void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_res
|
||||
|
||||
if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER == ra->preambleTransMax + 1){
|
||||
|
||||
LOG_D(MAC, "In %s: [UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n",
|
||||
__FUNCTION__, mod_id, frame, slot, ra->preambleTransMax);
|
||||
LOG_D(MAC, "[UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n",
|
||||
mac->ue_id,
|
||||
frame,
|
||||
slot,
|
||||
ra->preambleTransMax);
|
||||
|
||||
ra->RA_backoff_cnt = rand_r(&seed) % (prach_resources->RA_PREAMBLE_BACKOFF + 1);
|
||||
prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
|
||||
prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += 2; // 2 dB increment
|
||||
prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id);
|
||||
prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id);
|
||||
|
||||
} else {
|
||||
// Resetting RA window
|
||||
|
||||
@@ -102,7 +102,7 @@ random-access procedure
|
||||
@param selected_rar_buffer the output buffer for storing the selected RAR header and RAR payload
|
||||
@returns timing advance or 0xffff if preamble doesn't match
|
||||
*/
|
||||
static void nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id);
|
||||
static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id);
|
||||
|
||||
int get_pucch0_mcs(const int O_ACK, const int O_SR, const int ack_payload, const int sr_payload)
|
||||
{
|
||||
@@ -198,14 +198,13 @@ int get_rnti_type(NR_UE_MAC_INST_t *mac, uint16_t rnti)
|
||||
return rnti_type;
|
||||
}
|
||||
|
||||
void nr_ue_decode_mib(module_id_t module_id, int cc_id)
|
||||
void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id)
|
||||
{
|
||||
LOG_D(MAC,"[L2][MAC] decode mib\n");
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
if (mac->mib->cellBarred == NR_MIB__cellBarred_barred) {
|
||||
LOG_W(MAC, "Cell is barred. Going back to sync mode.\n");
|
||||
mac->synch_request.Mod_id = module_id;
|
||||
mac->synch_request.Mod_id = mac->ue_id;
|
||||
mac->synch_request.CC_id = cc_id;
|
||||
mac->synch_request.synch_req.target_Nid_cell = -1;
|
||||
mac->if_module->synch_request(&mac->synch_request);
|
||||
@@ -259,17 +258,16 @@ void nr_ue_decode_mib(module_id_t module_id, int cc_id)
|
||||
mac->state = UE_SYNC;
|
||||
}
|
||||
|
||||
int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id,
|
||||
int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint8_t ack_nack,
|
||||
uint8_t *pduP,
|
||||
uint32_t pdu_len)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
if(ack_nack) {
|
||||
LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n");
|
||||
nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
|
||||
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len);
|
||||
mac->get_sib1 = false;
|
||||
mac->get_otherSI = false;
|
||||
}
|
||||
@@ -370,9 +368,13 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_index, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci) {
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
int nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
int gNB_index,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
fapi_nr_dci_indication_pdu_t *dci)
|
||||
{
|
||||
dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][dci->dci_format];
|
||||
|
||||
LOG_D(MAC,"Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n",
|
||||
@@ -384,10 +386,10 @@ int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_in
|
||||
dci->dci_format = (dci->dci_format == NR_UL_DCI_FORMAT_0_0) ? NR_DL_DCI_FORMAT_1_0 : NR_UL_DCI_FORMAT_0_0;
|
||||
def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][dci->dci_format];
|
||||
}
|
||||
return nr_ue_process_dci(module_id, cc_id, frame, slot, def_dci_pdu_rel15, dci);
|
||||
return nr_ue_process_dci(mac, cc_id, frame, slot, def_dci_pdu_rel15, dci);
|
||||
}
|
||||
|
||||
static int nr_ue_process_dci_ul_00(module_id_t module_id,
|
||||
static int nr_ue_process_dci_ul_00(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
@@ -413,7 +415,6 @@ static int nr_ue_process_dci_ul_00(module_id_t module_id,
|
||||
// in which ULSCH should be scheduled. K2 is configured in RRC configuration.
|
||||
// todo:
|
||||
// - SUL_IND_0_0
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
// Schedule PUSCH
|
||||
const int coreset_type = dci_ind->coreset_type == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; // 0 for coreset0, 1 otherwise;
|
||||
@@ -444,7 +445,7 @@ static int nr_ue_process_dci_ul_00(module_id_t module_id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nr_ue_process_dci_ul_01(module_id_t module_id,
|
||||
static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
@@ -483,7 +484,6 @@ static int nr_ue_process_dci_ul_01(module_id_t module_id,
|
||||
// - FIRST_DAI
|
||||
// - SECOND_DAI
|
||||
// - SRS_RESOURCE_IND
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
/* SRS_REQUEST */
|
||||
AssertFatal(dci->srs_request.nbits == 2, "If SUL is supported in the cell, there is an additional bit in SRS request field\n");
|
||||
@@ -518,7 +518,7 @@ static int nr_ue_process_dci_ul_01(module_id_t module_id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nr_ue_process_dci_dl_10(module_id_t module_id,
|
||||
static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
@@ -575,7 +575,6 @@ static int nr_ue_process_dci_dl_10(module_id_t module_id,
|
||||
* 28 DAI_: For format1_1: 4 if more than one serving cell are configured in the DL and the higher layer parameter HARQ-ACK-codebook=dynamic, where the 2 MSB bits are the counter DAI and the 2 LSB bits are the total DAI
|
||||
* 33 TPC_PUCCH:
|
||||
*/
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot);
|
||||
fapi_nr_dl_config_request_pdu_t *dl_conf_req = &dl_config->dl_config_list[dl_config->number_pdus];
|
||||
@@ -852,7 +851,7 @@ static inline uint16_t packBits(const uint8_t *toPack, const int nb)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int nr_ue_process_dci_dl_11(module_id_t module_id,
|
||||
static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
@@ -888,7 +887,6 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id,
|
||||
* 44 CBGFI:
|
||||
* 47 DMRS_SEQ_INI:
|
||||
*/
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
if (dci->bwp_indicator.val > NR_MAX_NUM_BWP) {
|
||||
LOG_W(NR_MAC,
|
||||
@@ -1220,7 +1218,7 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t nr_ue_process_dci(module_id_t module_id,
|
||||
int8_t nr_ue_process_dci(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
@@ -1232,19 +1230,19 @@ int8_t nr_ue_process_dci(module_id_t module_id,
|
||||
|
||||
switch (dci_ind->dci_format) {
|
||||
case NR_UL_DCI_FORMAT_0_0:
|
||||
return nr_ue_process_dci_ul_00(module_id, cc_id, frame, slot, dci, dci_ind);
|
||||
return nr_ue_process_dci_ul_00(mac, cc_id, frame, slot, dci, dci_ind);
|
||||
break;
|
||||
|
||||
case NR_UL_DCI_FORMAT_0_1:
|
||||
return nr_ue_process_dci_ul_01(module_id, cc_id, frame, slot, dci, dci_ind);
|
||||
return nr_ue_process_dci_ul_01(mac, cc_id, frame, slot, dci, dci_ind);
|
||||
break;
|
||||
|
||||
case NR_DL_DCI_FORMAT_1_0:
|
||||
return nr_ue_process_dci_dl_10(module_id, cc_id, frame, slot, dci, dci_ind);
|
||||
return nr_ue_process_dci_dl_10(mac, cc_id, frame, slot, dci, dci_ind);
|
||||
break;
|
||||
|
||||
case NR_DL_DCI_FORMAT_1_1:
|
||||
return nr_ue_process_dci_dl_11(module_id, cc_id, frame, slot, dci, dci_ind);
|
||||
return nr_ue_process_dci_dl_11(mac, cc_id, frame, slot, dci, dci_ind);
|
||||
break;
|
||||
|
||||
case NR_DL_DCI_FORMAT_2_0:
|
||||
@@ -1270,12 +1268,11 @@ int8_t nr_ue_process_dci(module_id_t module_id,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int8_t nr_ue_process_csirs_measurements(module_id_t module_id,
|
||||
int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
fapi_nr_csirs_measurements_t *csirs_measurements) {
|
||||
LOG_D(NR_MAC,"(%d.%d) Received CSI-RS measurements\n", frame, slot);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
memcpy(&mac->csirs_measurements, csirs_measurements, sizeof(*csirs_measurements));
|
||||
return 0;
|
||||
}
|
||||
@@ -2449,14 +2446,15 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p
|
||||
return sr_count > 0 ? true : false;
|
||||
}
|
||||
|
||||
int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slot)
|
||||
int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slot)
|
||||
{
|
||||
// no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info;
|
||||
int max_sr_transmissions = (1 << (2 + si->sr_TransMax));
|
||||
LOG_D(NR_MAC, "[UE %d] Frame %d slot %d send SR indication (SR_COUNTER/sr_TransMax %d/%d), SR_pending %d\n",
|
||||
module_idP, frameP, slot,
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
slot,
|
||||
si->SR_COUNTER,
|
||||
max_sr_transmissions,
|
||||
si->SR_pending); // todo
|
||||
@@ -2464,7 +2462,9 @@ int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slot)
|
||||
if ((si->SR_pending == 1) &&
|
||||
(si->SR_COUNTER < max_sr_transmissions)) {
|
||||
LOG_D(NR_MAC, "[UE %d] Frame %d slot %d PHY asks for SR (SR_COUNTER/sr_TransMax %d/%d), SR_pending %d, increment SR_COUNTER\n",
|
||||
module_idP, frameP, slot,
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
slot,
|
||||
si->SR_COUNTER,
|
||||
max_sr_transmissions,
|
||||
si->SR_pending); // todo
|
||||
@@ -2489,7 +2489,7 @@ int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slot)
|
||||
//mac->ul_active = 0; // todo
|
||||
mac->BSR_reporting_active =
|
||||
NR_BSR_TRIGGER_NONE;
|
||||
LOG_I(NR_MAC, "[UE %d] Release all SRs \n", module_idP);
|
||||
LOG_I(NR_MAC, "[UE %d] Release all SRs \n", mac->ue_id);
|
||||
}
|
||||
si->SR_pending = 0;
|
||||
si->SR_COUNTER = 0;
|
||||
@@ -2852,7 +2852,7 @@ uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp) {
|
||||
|
||||
}
|
||||
|
||||
void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
{
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
|
||||
|
||||
@@ -2863,10 +2863,10 @@ void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
// it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs
|
||||
switch (dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type){
|
||||
case FAPI_NR_RX_PDU_TYPE_DLSCH:
|
||||
nr_ue_process_mac_pdu(dl_info, pdu_id);
|
||||
nr_ue_process_mac_pdu(mac, dl_info, pdu_id);
|
||||
break;
|
||||
case FAPI_NR_RX_PDU_TYPE_RAR:
|
||||
nr_ue_process_rar(dl_info, pdu_id);
|
||||
nr_ue_process_rar(mac, dl_info, pdu_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -3589,26 +3589,27 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
|
||||
// F: lenght of L is 0:8 or 1:16 bits wide
|
||||
// R: Reserved bit, set to zero.
|
||||
////////////////////////////////
|
||||
void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
int pdu_id)
|
||||
void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
{
|
||||
|
||||
module_id_t module_idP = dl_info->module_id;
|
||||
frame_t frameP = dl_info->frame;
|
||||
int slot = dl_info->slot;
|
||||
uint8_t *pduP = (dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu;
|
||||
int32_t pdu_len = (int32_t)(dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu_length;
|
||||
uint8_t gNB_index = dl_info->gNB_index;
|
||||
uint8_t CC_id = dl_info->cc_id;
|
||||
uint8_t done = 0;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
frame_t frameP = dl_info->frame;
|
||||
int slot = dl_info->slot;
|
||||
uint8_t *pduP = (dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu;
|
||||
int32_t pdu_len = (int32_t)(dl_info->rx_ind->rx_indication_body + pdu_id)->pdsch_pdu.pdu_length;
|
||||
uint8_t gNB_index = dl_info->gNB_index;
|
||||
uint8_t CC_id = dl_info->cc_id;
|
||||
uint8_t done = 0;
|
||||
RA_config_t *ra = &mac->ra;
|
||||
|
||||
if (!pduP){
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_D(MAC, "In %s [%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", __FUNCTION__, frameP, slot, pdu_id, pdu_len, dl_info->rx_ind->number_pdus);
|
||||
LOG_D(MAC, "[%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n",
|
||||
frameP,
|
||||
slot,
|
||||
pdu_id,
|
||||
pdu_len,
|
||||
dl_info->rx_ind->number_pdus);
|
||||
|
||||
while (!done && pdu_len > 0){
|
||||
uint16_t mac_len = 0x0000;
|
||||
@@ -3623,8 +3624,7 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
// MSG4 RRC Setup 38.331
|
||||
// variable length
|
||||
ret=get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len);
|
||||
AssertFatal(ret, "The mac_len (%d) has an invalid size. PDU len = %d! \n",
|
||||
mac_len, pdu_len);
|
||||
AssertFatal(ret, "The mac_len (%d) has an invalid size. PDU len = %d! \n", mac_len, pdu_len);
|
||||
|
||||
// Check if it is a valid CCCH message, we get all 00's messages very often
|
||||
int i = 0;
|
||||
@@ -3634,7 +3634,7 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
}
|
||||
}
|
||||
if (i == (mac_subheader_len+mac_len)) {
|
||||
LOG_D(NR_MAC, "%s() Invalid CCCH message!, pdu_len: %d\n", __func__, pdu_len);
|
||||
LOG_E(NR_MAC, "Invalid CCCH message!, pdu_len: %d\n", pdu_len);
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
@@ -3648,9 +3648,9 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
LOG_D(NR_MAC, "%d: 0x%x\n", i, pduP[mac_subheader_len + i]);
|
||||
}
|
||||
|
||||
mac_rlc_data_ind(module_idP,
|
||||
mac_rlc_data_ind(mac->ue_id,
|
||||
mac->ue_id,
|
||||
module_idP,
|
||||
gNB_index,
|
||||
frameP,
|
||||
ENB_FLAG_NO,
|
||||
MBMS_FLAG_NO,
|
||||
@@ -3737,9 +3737,21 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
*/
|
||||
|
||||
if (ta == 31)
|
||||
LOG_D(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d TA total %d\n", frameP, slot, ta, tag, CC_id, ul_time_alignment->ta_total);
|
||||
LOG_D(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d TA total %d\n",
|
||||
frameP,
|
||||
slot,
|
||||
ta,
|
||||
tag,
|
||||
CC_id,
|
||||
ul_time_alignment->ta_total);
|
||||
else
|
||||
LOG_I(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d TA total %d\n", frameP, slot, ta, tag, CC_id, ul_time_alignment->ta_total);
|
||||
LOG_I(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d TA total %d\n",
|
||||
frameP,
|
||||
slot,
|
||||
ta,
|
||||
tag,
|
||||
CC_id,
|
||||
ul_time_alignment->ta_total);
|
||||
|
||||
break;
|
||||
case DL_SCH_LCID_CON_RES_ID:
|
||||
@@ -3750,7 +3762,14 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
|
||||
if(ra->ra_state == WAIT_CONTENTION_RESOLUTION) {
|
||||
LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n",
|
||||
module_idP, frameP, pduP[1], pduP[2], pduP[3], pduP[4], pduP[5], pduP[6]);
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
pduP[1],
|
||||
pduP[2],
|
||||
pduP[3],
|
||||
pduP[4],
|
||||
pduP[5],
|
||||
pduP[6]);
|
||||
|
||||
bool ra_success = true;
|
||||
if (!IS_SOFTMODEM_IQPLAYER) { // Control is bypassed when replaying IQs (BMC)
|
||||
@@ -3763,7 +3782,7 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
}
|
||||
|
||||
if ( (ra->RA_active == 1) && ra_success) {
|
||||
nr_ra_succeeded(module_idP, gNB_index, frameP, slot);
|
||||
nr_ra_succeeded(mac, gNB_index, frameP, slot);
|
||||
} else if (!ra_success){
|
||||
// TODO: Handle failure of RA procedure @ MAC layer
|
||||
// nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure
|
||||
@@ -3783,7 +3802,7 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
return;
|
||||
LOG_D(NR_MAC, "%4d.%2d : DLSCH -> LCID %d %d bytes\n", frameP, slot, rx_lcid, mac_len);
|
||||
|
||||
mac_rlc_data_ind(module_idP,
|
||||
mac_rlc_data_ind(mac->ue_id,
|
||||
mac->ue_id,
|
||||
gNB_index,
|
||||
frameP,
|
||||
@@ -3798,12 +3817,12 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
|
||||
default:
|
||||
LOG_W(MAC, "unknown lcid %02x\n", rx_lcid);
|
||||
break;
|
||||
}
|
||||
pduP += ( mac_subheader_len + mac_len );
|
||||
pdu_len -= ( mac_subheader_len + mac_len );
|
||||
if (pdu_len < 0)
|
||||
LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", module_idP, frameP, slot, pdu_len);
|
||||
}
|
||||
pduP += ( mac_subheader_len + mac_len );
|
||||
pdu_len -= ( mac_subheader_len + mac_len );
|
||||
if (pdu_len < 0)
|
||||
LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", mac->ue_id, frameP, slot, pdu_len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3820,8 +3839,8 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
|
||||
uint16_t *crnti,
|
||||
NR_BSR_SHORT *truncated_bsr,
|
||||
NR_BSR_SHORT *short_bsr,
|
||||
NR_BSR_LONG *long_bsr) {
|
||||
|
||||
NR_BSR_LONG *long_bsr)
|
||||
{
|
||||
int mac_ce_len = 0;
|
||||
uint8_t mac_ce_size = 0;
|
||||
uint8_t *pdu = mac_ce;
|
||||
@@ -4009,41 +4028,39 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
|
||||
// - b buffer
|
||||
// - ulsch power offset
|
||||
// - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures
|
||||
static void nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
{
|
||||
module_id_t mod_id = dl_info->module_id;
|
||||
frame_t frame = dl_info->frame;
|
||||
int slot = dl_info->slot;
|
||||
frame_t frame = dl_info->frame;
|
||||
int slot = dl_info->slot;
|
||||
|
||||
if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack == 0) {
|
||||
LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] CRC check failed on RAR (NAK)\n", mod_id, frame, slot);
|
||||
LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] CRC check failed on RAR (NAK)\n", mac->ue_id, frame, slot);
|
||||
return;
|
||||
}
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
RA_config_t *ra = &mac->ra;
|
||||
uint8_t n_subPDUs = 0; // number of RAR payloads
|
||||
uint8_t n_subheaders = 0; // number of MAC RAR subheaders
|
||||
uint8_t *dlsch_buffer = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu;
|
||||
uint8_t is_Msg3 = 1;
|
||||
frame_t frame_tx = 0;
|
||||
int slot_tx = 0;
|
||||
int ret = 0;
|
||||
RA_config_t *ra = &mac->ra;
|
||||
uint8_t n_subPDUs = 0; // number of RAR payloads
|
||||
uint8_t n_subheaders = 0; // number of MAC RAR subheaders
|
||||
uint8_t *dlsch_buffer = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu;
|
||||
uint8_t is_Msg3 = 1;
|
||||
frame_t frame_tx = 0;
|
||||
int slot_tx = 0;
|
||||
int ret = 0;
|
||||
NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer
|
||||
NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer
|
||||
uint8_t preamble_index = ra->ra_PreambleIndex;
|
||||
NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer
|
||||
uint8_t preamble_index = ra->ra_PreambleIndex;
|
||||
|
||||
LOG_D(NR_MAC, "In %s:[%d.%d]: [UE %d][RAPROC] invoking MAC for received RAR (current preamble %d)\n", __FUNCTION__, frame, slot, mod_id, preamble_index);
|
||||
LOG_D(NR_MAC, "[%d.%d]: [UE %d][RAPROC] invoking MAC for received RAR (current preamble %d)\n", frame, slot, mac->ue_id, preamble_index);
|
||||
|
||||
while (1) {
|
||||
n_subheaders++;
|
||||
if (rarh->T == 1) {
|
||||
n_subPDUs++;
|
||||
LOG_I(NR_MAC, "[UE %d][RAPROC] Got RAPID RAR subPDU\n", mod_id);
|
||||
LOG_I(NR_MAC, "[UE %d][RAPROC] Got RAPID RAR subPDU\n", mac->ue_id);
|
||||
} else {
|
||||
ra->RA_backoff_indicator = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI];
|
||||
ra->RA_BI_found = 1;
|
||||
LOG_I(NR_MAC, "[UE %d][RAPROC] Got BI RAR subPDU %d ms\n", mod_id, ra->RA_backoff_indicator);
|
||||
LOG_I(NR_MAC, "[UE %d][RAPROC] Got BI RAR subPDU %d ms\n", mac->ue_id, ra->RA_backoff_indicator);
|
||||
if ( ((NR_RA_HEADER_BI *)rarh)->E == 1) {
|
||||
rarh += sizeof(NR_RA_HEADER_BI);
|
||||
continue;
|
||||
@@ -4052,7 +4069,7 @@ static void nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
}
|
||||
}
|
||||
if (rarh->RAPID == preamble_index) {
|
||||
LOG_A(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mod_id, frame, slot, rarh->RAPID);
|
||||
LOG_A(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mac->ue_id, frame, slot, rarh->RAPID);
|
||||
rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR));
|
||||
ra->RA_RAPID_found = 1;
|
||||
if (get_softmodem_params()->emulate_l1) {
|
||||
@@ -4073,7 +4090,12 @@ static void nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
break;
|
||||
}
|
||||
if (rarh->E == 0) {
|
||||
LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] Received RAR preamble (%d) doesn't match the intended RAPID (%d)\n", mod_id, frame, slot, rarh->RAPID, preamble_index);
|
||||
LOG_W(NR_MAC,"[UE %d][RAPROC][%d.%d] Received RAR preamble (%d) doesn't match the intended RAPID (%d)\n",
|
||||
mac->ue_id,
|
||||
frame,
|
||||
slot,
|
||||
rarh->RAPID,
|
||||
preamble_index);
|
||||
break;
|
||||
} else {
|
||||
rarh += sizeof(NR_MAC_RAR) + 1;
|
||||
@@ -4081,8 +4103,21 @@ static void nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
}
|
||||
|
||||
#ifdef DEBUG_RAR
|
||||
LOG_D(MAC, "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", frame, slot, n_subheaders, n_subPDUs);
|
||||
LOG_D(MAC, "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index);
|
||||
LOG_D(MAC, "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n",
|
||||
frame,
|
||||
slot,
|
||||
n_subheaders,
|
||||
n_subPDUs);
|
||||
LOG_D(MAC, "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n",
|
||||
*(uint8_t *) rarh,
|
||||
rar[0],
|
||||
rar[1],
|
||||
rar[2],
|
||||
rar[3],
|
||||
rar[4],
|
||||
rar[5],
|
||||
rarh->RAPID,
|
||||
preamble_index);
|
||||
#endif
|
||||
|
||||
if (ra->RA_RAPID_found) {
|
||||
@@ -4162,17 +4197,16 @@ static void nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1);
|
||||
LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2);
|
||||
|
||||
LOG_I(NR_MAC, "In %s:[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d\n",
|
||||
__FUNCTION__,
|
||||
frame,
|
||||
slot,
|
||||
mod_id,
|
||||
rar_grant.Msg3_t_alloc,
|
||||
rar_grant.Msg3_f_alloc,
|
||||
ta_command,
|
||||
rar_grant.mcs,
|
||||
rar_grant.freq_hopping,
|
||||
tpc_command);
|
||||
LOG_I(NR_MAC, "[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d\n",
|
||||
frame,
|
||||
slot,
|
||||
mac->ue_id,
|
||||
rar_grant.Msg3_t_alloc,
|
||||
rar_grant.Msg3_f_alloc,
|
||||
ta_command,
|
||||
rar_grant.mcs,
|
||||
rar_grant.freq_hopping,
|
||||
tpc_command);
|
||||
#endif
|
||||
|
||||
// Schedule Msg3
|
||||
@@ -4196,7 +4230,7 @@ static void nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
if (!ra->cfra) {
|
||||
ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
|
||||
rnti = ra->t_crnti;
|
||||
nr_mac_rrc_msg3_ind(mod_id, rnti);
|
||||
nr_mac_rrc_msg3_ind(mac->ue_id, rnti);
|
||||
}
|
||||
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH);
|
||||
if (!pdu)
|
||||
@@ -4211,7 +4245,6 @@ static void nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id)
|
||||
} else {
|
||||
ra->t_crnti = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "mac_defs_sl.h"
|
||||
|
||||
#define SL_DEBUG
|
||||
|
||||
uint8_t sl_process_TDD_UL_DL_config_patterns(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
|
||||
uint8_t mu,
|
||||
double *slot_period_P,
|
||||
uint8_t *w)
|
||||
{
|
||||
|
||||
uint8_t return_value = 255;
|
||||
*w = 0;
|
||||
int pattern1_dlul_period = TDD_UL_DL_Config->pattern1.dl_UL_TransmissionPeriodicity;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
|
||||
printf("INPUT VALUES: function: %s\n", __func__);
|
||||
printf("pattern1 periodicity:%d\n", pattern1_dlul_period);
|
||||
if (TDD_UL_DL_Config->pattern1.ext1 != NULL && TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL )
|
||||
printf("pattern1 periodicity_v1530:%ld\n", *TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530);
|
||||
if (TDD_UL_DL_Config->pattern2 != NULL) {
|
||||
printf("mu:%d, pattern2 periodicity:%d\n", mu, pattern1_dlul_period);
|
||||
if (TDD_UL_DL_Config->pattern2->ext1 != NULL && TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL )
|
||||
printf("pattern2 periodicity_v1530:%ld\n", *TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return_value = pattern1_dlul_period;
|
||||
switch (pattern1_dlul_period) {
|
||||
case 0:
|
||||
*slot_period_P = 0.5;
|
||||
break;
|
||||
case 1:
|
||||
*slot_period_P = 0.625;
|
||||
break;
|
||||
case 2:
|
||||
*slot_period_P = 1.0;
|
||||
break;
|
||||
case 3:
|
||||
*slot_period_P = 1.25;
|
||||
break;
|
||||
case 4:
|
||||
*slot_period_P = 2.0;
|
||||
break;
|
||||
case 5:
|
||||
*slot_period_P = 2.5;
|
||||
break;
|
||||
case 6:
|
||||
*slot_period_P = 5.0;
|
||||
return_value = 7;
|
||||
break;
|
||||
case 7:
|
||||
*slot_period_P = 10.0;
|
||||
return_value = 8;
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Incorrect value of dl_UL_TransmissionPeriodicity\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (TDD_UL_DL_Config->pattern1.ext1 != NULL &&
|
||||
TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL ) {
|
||||
if (*TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 == 1) {
|
||||
*slot_period_P = 4.0;
|
||||
return_value = 6;
|
||||
} else {
|
||||
*slot_period_P = 3.0;
|
||||
return_value = 255;
|
||||
}
|
||||
}
|
||||
|
||||
if (TDD_UL_DL_Config->pattern2 != NULL) {
|
||||
|
||||
return_value = 255;
|
||||
*w = 1;
|
||||
|
||||
if ((*slot_period_P == 4.0 ) && (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 1)) {
|
||||
return_value = 13;
|
||||
*w = (mu == 3)? 2: 1;
|
||||
} else if ((*slot_period_P == 3.0 ) && (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 4)) {
|
||||
return_value = 12;
|
||||
*w = (mu == 3)? 2: 1;
|
||||
} else if ((*slot_period_P == 3.0 ) && (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 2)) {
|
||||
return_value = 8;
|
||||
*w = (mu == 3)? 2: 1;
|
||||
} else {
|
||||
|
||||
switch (pattern1_dlul_period) {
|
||||
case 7:
|
||||
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 7) {
|
||||
return_value = 15;
|
||||
*w = 1<<mu;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 6) {
|
||||
return_value = 14;
|
||||
*w = (mu==0)?1:1<<(mu-1);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 5) {
|
||||
return_value = 11;
|
||||
*w = (mu == 3)? 2: 1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 0) {
|
||||
return_value = 5;
|
||||
}
|
||||
else if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 4) {
|
||||
return_value = 7;
|
||||
}
|
||||
else if (TDD_UL_DL_Config->pattern2->ext1 != NULL && *TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 == 0) {
|
||||
return_value = 10;
|
||||
*w = (mu == 3)? 2: 1;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 3) {
|
||||
return_value = 4;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 2) {
|
||||
return_value = 2;
|
||||
}
|
||||
else if (TDD_UL_DL_Config->pattern2->ext1 != NULL && *TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 == 0) {
|
||||
return_value = 6;
|
||||
*w = (mu == 3)? 2: 1;
|
||||
}
|
||||
else if (TDD_UL_DL_Config->pattern2->ext1 != NULL && *TDD_UL_DL_Config->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 == 1) {
|
||||
return_value = 9;
|
||||
*w = (mu == 3)? 2: 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 1) {
|
||||
return_value = 1;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 0) {
|
||||
return_value = 0;
|
||||
}
|
||||
else if (TDD_UL_DL_Config->pattern2->dl_UL_TransmissionPeriodicity == 4) {
|
||||
return_value = 3;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0,"Incorrect value of dl_UL_TransmissionPeriodicity");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("OUTPUT VALUES: function %s\n",__func__);
|
||||
printf("return_value:%d, *w:%d, slot_period_P:%f\n", return_value, *w, *slot_period_P);
|
||||
#endif
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/*
|
||||
This procedures prepares the psbch payload of tdd configuration according
|
||||
to section 16.1 in 38.213
|
||||
*/
|
||||
void sl_prepare_psbch_payload(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
|
||||
uint8_t *bits_0_to_7, uint8_t *bits_8_to_11,
|
||||
uint8_t mu, uint8_t L, uint8_t Y)
|
||||
{
|
||||
|
||||
uint8_t w = 0, a1_to_a4 = 0;
|
||||
uint8_t mu_ref = 0, diff = 0;
|
||||
uint8_t u_slots = 0, u_sym = 0, I1 = 0;
|
||||
uint8_t u_sl_slots = 0, u_sl_slots_2 = 0;
|
||||
double slot_period_P = 0.0;
|
||||
|
||||
*bits_0_to_7 = 0xFF; // If TDD_UL_DL_Config = NULL all 12 bits are set to 1
|
||||
*bits_8_to_11 = 0xF0;
|
||||
|
||||
if (TDD_UL_DL_Config != NULL) {
|
||||
|
||||
mu_ref = TDD_UL_DL_Config->referenceSubcarrierSpacing;
|
||||
diff = 1 << (mu-mu_ref);
|
||||
u_slots = TDD_UL_DL_Config->pattern1.nrofUplinkSlots;
|
||||
u_sym = TDD_UL_DL_Config->pattern1.nrofUplinkSymbols;
|
||||
I1 = ((u_sym * diff) % L >= (L-Y)) ? 1 : 0;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("INPUT VALUES: function %s\n", __func__);
|
||||
printf("numerology:%d, number of symbols:%d, sl-startSymbol:%d\n", mu, L, Y);
|
||||
printf("mu_ref:%d, u_slots:%d, u_sym:%d\n", mu_ref, u_slots, u_sym);
|
||||
if (TDD_UL_DL_Config->pattern2 != NULL)
|
||||
printf("u_slots_2:%ld, u_sym_2:%ld\n", TDD_UL_DL_Config->pattern2->nrofUplinkSlots,
|
||||
TDD_UL_DL_Config->pattern2->nrofUplinkSymbols);
|
||||
#endif
|
||||
|
||||
u_sl_slots = (u_slots * diff) + floor((u_sym*diff)/L) + I1;
|
||||
a1_to_a4 = sl_process_TDD_UL_DL_config_patterns(TDD_UL_DL_Config, mu, &slot_period_P, &w);
|
||||
AssertFatal(a1_to_a4 != 255,"Incorrect return value, wrong configuration.\n");
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("I1:%d, a1_to_a2:%d, u_sl_slots:%d\n", I1, a1_to_a4, u_sl_slots);
|
||||
#endif
|
||||
|
||||
if (TDD_UL_DL_Config->pattern2 != NULL) {
|
||||
|
||||
uint8_t u_slots_2 = TDD_UL_DL_Config->pattern2->nrofUplinkSlots;
|
||||
uint8_t u_sym_2 = TDD_UL_DL_Config->pattern2->nrofUplinkSymbols;
|
||||
uint8_t I2 = ((u_sym_2 * diff) % L >= (L-Y)) ? 1 : 0;
|
||||
uint16_t val = floor(((u_slots_2 * diff) + floor((u_sym_2*diff)/L) + I2)/w);
|
||||
|
||||
u_sl_slots_2 = val * ceil((slot_period_P*(1<<mu)+1)/w) + floor(u_sl_slots/w);
|
||||
|
||||
*bits_0_to_7 = 0x80 | (a1_to_a4 << 3) | ((u_sl_slots_2 & 0x70) >> 4);
|
||||
*bits_8_to_11 = (u_sl_slots_2 & 0x0F) << 4;
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("I2:%d, val:%d, u_sl_slots_2:%d\n", I2, val, u_sl_slots_2);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
*bits_0_to_7 = 0x00 | (a1_to_a4 << 3) | ((u_sl_slots & 0x70) >> 4);
|
||||
*bits_8_to_11 = (u_sl_slots & 0x0F) << 4;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("OUTPUT VALUES: function %s\n", __func__);
|
||||
printf("12 bits payload buf[0]:%x, buf[1]:%x\n", *bits_0_to_7, *bits_8_to_11);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
This procedures prepares the psbch payload of tdd configuration according
|
||||
to section 16.1 in 38.213
|
||||
*/
|
||||
uint8_t sl_decode_sl_TDD_Config(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
|
||||
uint8_t bits_0_to_7, uint8_t bits_8_to_11,
|
||||
uint8_t mu, uint8_t L, uint8_t Y)
|
||||
{
|
||||
|
||||
AssertFatal(TDD_UL_DL_Config, "TDD_UL_DL_Config cannot be null");
|
||||
uint16_t num_SL_slots = 0, mixed_slot_numsym = 0;
|
||||
|
||||
TDD_UL_DL_Config->pattern1.nrofDownlinkSlots = 0;
|
||||
TDD_UL_DL_Config->pattern1.nrofDownlinkSymbols = 0;
|
||||
TDD_UL_DL_Config->pattern1.nrofUplinkSlots = 0;
|
||||
TDD_UL_DL_Config->pattern1.nrofUplinkSymbols = 0;
|
||||
TDD_UL_DL_Config->referenceSubcarrierSpacing = mu;
|
||||
TDD_UL_DL_Config->pattern1.ext1 = NULL;
|
||||
|
||||
LOG_D(MAC, "bits_0_to_7:%x, bits_8_to_11:%x, mu:%d, L:%d, Y:%d\n",
|
||||
bits_0_to_7, bits_8_to_11,mu, L, Y);
|
||||
|
||||
//If all bits are 1 - indicates that no TDD config was present.
|
||||
if ((bits_0_to_7 == 0xFF) && ((bits_8_to_11 & 0xF0) == 0xF0)) {
|
||||
//If no TDD config present - use all slots for Sidelink.
|
||||
//Spec not clear -- TBD....
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Bit A0 if 1 indicates pattern2 as present.
|
||||
if (bits_0_to_7 & 0x80) {
|
||||
//Pattern1 and Pattern2 Present.
|
||||
TDD_UL_DL_Config->pattern2 = malloc16_clear(sizeof(*TDD_UL_DL_Config->pattern2));
|
||||
AssertFatal(1==0,"Decoding Pattern2 - NOT YET IMPLEMENTED\n");
|
||||
} else {
|
||||
|
||||
//Only Pattern1 Present. bits a1..a4 identify the periodicity.
|
||||
uint8_t val = (bits_0_to_7 & 0x78) >> 3;
|
||||
if (val >= 7)
|
||||
TDD_UL_DL_Config->pattern1.dl_UL_TransmissionPeriodicity = val-1;
|
||||
|
||||
if (val == 6) {
|
||||
if (TDD_UL_DL_Config->pattern1.ext1 == NULL)
|
||||
TDD_UL_DL_Config->pattern1.ext1 = calloc(1, sizeof(*TDD_UL_DL_Config->pattern1.ext1));
|
||||
if (TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 == NULL)
|
||||
TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 = calloc(1, sizeof(long));
|
||||
*TDD_UL_DL_Config->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 = 1;
|
||||
}
|
||||
|
||||
//a5,a6..a11 bits from the 7th to 1st LSB of num SL slots
|
||||
num_SL_slots = ((bits_0_to_7 & 0x07) << 4 ) | ((bits_8_to_11 & 0xF0) >> 4);
|
||||
|
||||
TDD_UL_DL_Config->pattern1.nrofUplinkSlots = num_SL_slots;
|
||||
TDD_UL_DL_Config->pattern1.nrofUplinkSymbols = mixed_slot_numsym;
|
||||
|
||||
LOG_D(MAC, "SIDELINK: EXtracted TDD config from 12 bits - Sidelink Slots:%ld, Mixed_slot_symbols:%ld,dl_UL_TransmissionPeriodicity:%ld\n",
|
||||
TDD_UL_DL_Config->pattern1.nrofUplinkSlots, TDD_UL_DL_Config->pattern1.nrofUplinkSymbols,
|
||||
TDD_UL_DL_Config->pattern1.dl_UL_TransmissionPeriodicity);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*Function used to prepare Sidelink MIB*/
|
||||
uint32_t sl_prepare_MIB(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
|
||||
uint8_t incoverage, uint8_t mu,
|
||||
uint8_t start_symbol, uint8_t L)
|
||||
{
|
||||
|
||||
uint8_t sl_mib_payload[4] = {0,0,0,0};
|
||||
//int mu = UE->sl_frame_params.numerology_index, start_symbol = UE->start_symbol;
|
||||
uint8_t byte0, byte1;
|
||||
//int L = (UE->sl_frame_params.Ncp == 0) ? 14 : 12;
|
||||
uint32_t sl_mib=0;
|
||||
|
||||
sl_prepare_psbch_payload(TDD_UL_DL_Config, &byte0, &byte1, mu, L, start_symbol);
|
||||
sl_mib_payload[0] = byte0;
|
||||
sl_mib_payload[1] = byte1;
|
||||
|
||||
AssertFatal(incoverage <= 1, "Invalid value for incoverage paramter for SL-MIB. Accepted values 0 or 1\n");
|
||||
sl_mib_payload[1] |= (incoverage << 3);
|
||||
|
||||
sl_mib = sl_mib_payload[1]<<8 | sl_mib_payload[0];
|
||||
|
||||
#ifdef SL_DEBUG
|
||||
printf("SIDELINK PSBCH SIM: NUM SYMBOLS:%d, mu:%d, start_symbol:%d incoverage:%d \n",
|
||||
L, mu, start_symbol, incoverage);
|
||||
printf("SIDELINK PSBCH PAYLOAD: psbch_a:%x, sl_mib_payload:%x %x %x %x\n",
|
||||
sl_mib, sl_mib_payload[0],sl_mib_payload[1], sl_mib_payload[2], sl_mib_payload[3]);
|
||||
#endif
|
||||
|
||||
return sl_mib;
|
||||
}
|
||||
|
||||
uint16_t sl_get_subchannel_size(NR_SL_ResourcePool_r16_t *rpool)
|
||||
{
|
||||
|
||||
uint16_t subch_size = 0;
|
||||
const uint8_t subchsizes[8] = {10, 12, 15, 20, 25, 50, 75, 100};
|
||||
|
||||
subch_size = (rpool->sl_SubchannelSize_r16)
|
||||
? subchsizes[*rpool->sl_SubchannelSize_r16] : 0;
|
||||
|
||||
AssertFatal(subch_size,"Subch Size cannot be 0.Resource Pool Configuration Error\n");
|
||||
|
||||
return subch_size;
|
||||
}
|
||||
|
||||
uint16_t sl_get_num_subch(NR_SL_ResourcePool_r16_t *rpool)
|
||||
{
|
||||
|
||||
uint16_t num_subch = 0;
|
||||
uint16_t subch_size = sl_get_subchannel_size(rpool);
|
||||
uint16_t num_rbs = (rpool->sl_RB_Number_r16) ? *rpool->sl_RB_Number_r16 : 0;
|
||||
|
||||
AssertFatal(num_rbs,"NumRbs in rpool cannot be 0.Resource Pool Configuration Error\n");
|
||||
|
||||
num_subch = num_rbs/subch_size;
|
||||
|
||||
LOG_I(NR_MAC, "Subch_size:%d, numRBS:%d, num_subch:%d\n",
|
||||
subch_size,num_rbs,num_subch);
|
||||
|
||||
return (num_subch);
|
||||
}
|
||||
|
||||
//This function determines SCI 1A Len in bits based on the configuration in the resource pool.
|
||||
uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels,
|
||||
NR_SL_ResourcePool_r16_t *rpool,
|
||||
sidelink_sci_format_1a_fields_t *sci_1a)
|
||||
{
|
||||
|
||||
uint8_t num_bits = 0;
|
||||
|
||||
//Size of Fixed fields prio (3), sci_2ndstage(2),
|
||||
//betaoffsetindicator(2), num dmrs ports (1), mcs (5bits)
|
||||
uint8_t sci_1a_len = SL_SCI_FORMAT_1A_LEN_IN_BITS_FIXED_FIELDS;
|
||||
|
||||
*num_subchannels = sl_get_num_subch(rpool);
|
||||
|
||||
uint16_t n_subch = *num_subchannels;
|
||||
|
||||
LOG_D(NR_MAC,"Determine SCI-1A len - Num Subch:%d, sci 1A len fixed fields:%d\n",
|
||||
*num_subchannels, sci_1a_len);
|
||||
|
||||
NR_SL_UE_SelectedConfigRP_r16_t *selectedconfigRP = rpool->sl_UE_SelectedConfigRP_r16;
|
||||
const uint8_t maxnum_values[] = {2,3};
|
||||
uint8_t sl_MaxNumPerReserve = (selectedconfigRP &&
|
||||
selectedconfigRP->sl_MaxNumPerReserve_r16)
|
||||
? maxnum_values[*selectedconfigRP->sl_MaxNumPerReserve_r16]
|
||||
: 0;
|
||||
|
||||
//Determine bits for Freq and Time Resource assignment
|
||||
if (sl_MaxNumPerReserve == 3) {
|
||||
num_bits = ceil(log2(n_subch * (n_subch + 1) * (2*n_subch + 1)/6));
|
||||
sci_1a_len += num_bits;
|
||||
sci_1a->frequency_resource_assignment.nbits = num_bits;
|
||||
sci_1a_len += 9;
|
||||
sci_1a->time_resource_assignment.nbits = 9;
|
||||
} else {
|
||||
num_bits = ceil(log2((n_subch * (n_subch + 1)) >> 1));
|
||||
sci_1a_len += num_bits;
|
||||
sci_1a->frequency_resource_assignment.nbits = num_bits;
|
||||
sci_1a_len += 5;
|
||||
sci_1a->time_resource_assignment.nbits = 5;
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC,"sci 1A - sl_MaxNumPerReserve:%d, sci 1a len:%d, FRA nbits:%d, TRA nbits:%d\n",
|
||||
sl_MaxNumPerReserve,sci_1a_len,
|
||||
sci_1a->frequency_resource_assignment.nbits,
|
||||
sci_1a->time_resource_assignment.nbits);
|
||||
|
||||
//Determine bits for res reservation period
|
||||
uint8_t n_rsvperiod = (selectedconfigRP &&
|
||||
selectedconfigRP->sl_ResourceReservePeriodList_r16)
|
||||
? selectedconfigRP->sl_ResourceReservePeriodList_r16->list.count : 0;
|
||||
|
||||
#define SL_IE_ENABLED 0
|
||||
if (selectedconfigRP &&
|
||||
selectedconfigRP->sl_MultiReserveResource_r16 == SL_IE_ENABLED) {
|
||||
num_bits = ceil(log2(n_rsvperiod));
|
||||
sci_1a_len += num_bits;
|
||||
sci_1a->resource_reservation_period.nbits = num_bits;
|
||||
} else
|
||||
sci_1a->resource_reservation_period.nbits = 0;
|
||||
|
||||
LOG_D(NR_MAC,"sci 1A - n_rsvperiod:%d, sci 1a len:%d, res reserve period.nbits:%d\n",
|
||||
n_rsvperiod, sci_1a_len,
|
||||
sci_1a->resource_reservation_period.nbits);
|
||||
|
||||
|
||||
uint8_t n_dmrspatterns = 0;
|
||||
if (rpool->sl_PSSCH_Config_r16 &&
|
||||
rpool->sl_PSSCH_Config_r16->present == NR_SetupRelease_SL_PSSCH_Config_r16_PR_setup) {
|
||||
NR_SL_PSSCH_Config_r16_t *pssch_cfg = rpool->sl_PSSCH_Config_r16->choice.setup;
|
||||
|
||||
//Determine bits for DMRS PATTERNS
|
||||
n_dmrspatterns = (pssch_cfg && pssch_cfg->sl_PSSCH_DMRS_TimePatternList_r16)
|
||||
? pssch_cfg->sl_PSSCH_DMRS_TimePatternList_r16->list.count : 0;
|
||||
}
|
||||
|
||||
AssertFatal((n_dmrspatterns>=1) && (n_dmrspatterns <=3),
|
||||
"Number of DMRS Patterns should be 1or2or3. Resource Pool Configuration Error.\n");
|
||||
|
||||
if (n_dmrspatterns) {
|
||||
num_bits = ceil(log2(n_dmrspatterns));
|
||||
sci_1a_len += num_bits;
|
||||
sci_1a->dmrs_pattern.nbits = num_bits;
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC,"sci 1A - n_dmrspatterns:%d, sci 1a len:%d, dmrs_pattern.nbits:%d\n",
|
||||
n_dmrspatterns, sci_1a_len, sci_1a->dmrs_pattern.nbits);
|
||||
|
||||
//Determine bits for Additional MCS table
|
||||
if (rpool->sl_Additional_MCS_Table_r16) {
|
||||
int numbits = (*rpool->sl_Additional_MCS_Table_r16 > 1) ? 2 : 1;
|
||||
sci_1a_len += numbits;
|
||||
sci_1a->additional_mcs_table_indicator.nbits = numbits;
|
||||
AssertFatal(*rpool->sl_Additional_MCS_Table_r16<=2, "additional table value cannot be > 2. Resource Pool Configuration Error.\n");
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC,"sci 1A - additional_table:%ld, sci 1a len:%d, additional table nbits:%d\n",
|
||||
*rpool->sl_Additional_MCS_Table_r16,
|
||||
sci_1a_len,
|
||||
sci_1a->additional_mcs_table_indicator.nbits);
|
||||
|
||||
uint8_t psfch_period = 0;
|
||||
if (rpool->sl_PSFCH_Config_r16 &&
|
||||
rpool->sl_PSFCH_Config_r16->present == NR_SetupRelease_SL_PSFCH_Config_r16_PR_setup) {
|
||||
NR_SL_PSFCH_Config_r16_t *psfch_config = rpool->sl_PSFCH_Config_r16->choice.setup;
|
||||
|
||||
//Determine bits for PSFCH overhead indication
|
||||
const uint8_t psfch_periods[] = {0,1,2,4};
|
||||
psfch_period = (psfch_config->sl_PSFCH_Period_r16)
|
||||
? psfch_periods[*psfch_config->sl_PSFCH_Period_r16] : 0;
|
||||
}
|
||||
|
||||
if ((psfch_period == 2) || (psfch_period == 4)) {
|
||||
sci_1a_len += 1;
|
||||
sci_1a->psfch_overhead_indication.nbits = 1;
|
||||
} else
|
||||
sci_1a->psfch_overhead_indication.nbits = 0;
|
||||
|
||||
LOG_D(NR_MAC,"sci 1A - psfch_period:%d, sci 1a len:%d, psfch overhead nbits:%d\n",
|
||||
psfch_period, sci_1a_len,
|
||||
sci_1a->psfch_overhead_indication.nbits);
|
||||
|
||||
//Determine number of reserved bits
|
||||
uint8_t num_reservedbits = 0;
|
||||
if (rpool->sl_PSCCH_Config_r16 &&
|
||||
rpool->sl_PSCCH_Config_r16->present == NR_SetupRelease_SL_PSCCH_Config_r16_PR_setup) {
|
||||
NR_SL_PSCCH_Config_r16_t *pscch_config = rpool->sl_PSCCH_Config_r16->choice.setup;
|
||||
|
||||
num_reservedbits = (pscch_config->sl_NumReservedBits_r16)
|
||||
? *pscch_config->sl_NumReservedBits_r16 : 0;
|
||||
}
|
||||
|
||||
AssertFatal((num_reservedbits>=2) || (num_reservedbits<=4) ,
|
||||
"Num Reserved bits can only be 2or3or4. Resource Pool Configuration Error.\n");
|
||||
sci_1a_len += num_reservedbits;
|
||||
sci_1a->reserved_bits.nbits = num_reservedbits;
|
||||
LOG_D(NR_MAC,"sci 1A - reserved_bits:%d, sci 1a len:%d, sci_1a->reserved_bits.nbits:%d\n",
|
||||
num_reservedbits, sci_1a_len, sci_1a->reserved_bits.nbits);
|
||||
|
||||
|
||||
LOG_D(NR_MAC,"sci 1A Length in bits: %d \n",sci_1a_len);
|
||||
|
||||
return sci_1a_len;
|
||||
}
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
//#define SRS_DEBUG
|
||||
|
||||
static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP);
|
||||
static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_frame_t slotP);
|
||||
|
||||
fapi_nr_ul_config_request_pdu_t *lockGet_ul_config(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int slot_tx, uint8_t pdu_type)
|
||||
{
|
||||
@@ -925,11 +925,9 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger
|
||||
|
||||
|
||||
// Periodic SRS scheduling
|
||||
bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slot)
|
||||
static bool nr_ue_periodic_srs_scheduling(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot)
|
||||
{
|
||||
bool srs_scheduled = false;
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
|
||||
|
||||
NR_SRS_Config_t *srs_config = current_UL_BWP ? current_UL_BWP->srs_Config : NULL;
|
||||
@@ -987,12 +985,10 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo
|
||||
// 1. TODO: Call RRC for link status return to PHY
|
||||
// 2. TODO: Perform SR/BSR procedures for scheduling feedback
|
||||
// 3. TODO: Perform PHR procedures
|
||||
void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info)
|
||||
void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info)
|
||||
{
|
||||
module_id_t mod_id = dl_info->module_id;
|
||||
frame_t rx_frame = dl_info->frame;
|
||||
slot_t rx_slot = dl_info->slot;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
frame_t rx_frame = dl_info->frame;
|
||||
slot_t rx_slot = dl_info->slot;
|
||||
|
||||
fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, rx_slot);
|
||||
dl_config->sfn = rx_frame;
|
||||
@@ -1012,7 +1008,7 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info)
|
||||
}
|
||||
|
||||
nr_scheduled_response_t scheduled_response = {.dl_config = dl_config,
|
||||
.module_id = dl_info->module_id,
|
||||
.module_id = mac->ue_id,
|
||||
.CC_id = dl_info->cc_id,
|
||||
.phy_data = dl_info->phy_data,
|
||||
.mac = mac};
|
||||
@@ -1022,24 +1018,22 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info)
|
||||
LOG_E(NR_MAC, "Internal error, no scheduled_response function\n");
|
||||
}
|
||||
|
||||
void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
|
||||
void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
|
||||
{
|
||||
int cc_id = ul_info->cc_id;
|
||||
int cc_id = ul_info->cc_id;
|
||||
frame_t frame_tx = ul_info->frame;
|
||||
slot_t slot_tx = ul_info->slot;
|
||||
module_id_t mod_id = ul_info->module_id;
|
||||
uint32_t gNB_index = ul_info->gNB_index;
|
||||
uint32_t gNB_index = ul_info->gNB_index;
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
|
||||
RA_config_t *ra = &mac->ra;
|
||||
if(mac->state < UE_CONNECTED) {
|
||||
nr_ue_get_rach(mod_id, cc_id, frame_tx, gNB_index, slot_tx);
|
||||
nr_ue_prach_scheduler(mod_id, frame_tx, slot_tx);
|
||||
nr_ue_get_rach(mac, cc_id, frame_tx, gNB_index, slot_tx);
|
||||
nr_ue_prach_scheduler(mac, frame_tx, slot_tx);
|
||||
}
|
||||
|
||||
// Periodic SRS scheduling
|
||||
if(mac->state == UE_CONNECTED)
|
||||
nr_ue_periodic_srs_scheduling(mod_id, frame_tx, slot_tx);
|
||||
nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx);
|
||||
|
||||
// Schedule ULSCH only if the current frame and slot match those in ul_config_req
|
||||
// AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus)
|
||||
@@ -1063,7 +1057,7 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
|
||||
TBS_bytes,
|
||||
ra->ra_state);
|
||||
if (ra->ra_state == WAIT_RAR && !ra->cfra) {
|
||||
nr_get_msg3_payload(mod_id, ulsch_input_buffer, TBS_bytes);
|
||||
nr_get_msg3_payload(mac, ulsch_input_buffer, TBS_bytes);
|
||||
for (int k = 0; k < TBS_bytes; k++) {
|
||||
LOG_D(NR_MAC, "(%i): 0x%x\n", k, ulsch_input_buffer[k]);
|
||||
}
|
||||
@@ -1072,7 +1066,7 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
|
||||
if (ulcfg_pdu->pusch_config_pdu.pusch_data.new_data_indicator
|
||||
&& (mac->state == UE_CONNECTED || (ra->ra_state == WAIT_RAR && ra->cfra))) {
|
||||
// Getting IP traffic to be transmitted
|
||||
nr_ue_get_sdu(mod_id, cc_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes);
|
||||
nr_ue_get_sdu(mac, cc_id, frame_tx, slot_tx, gNB_index, ulsch_input_buffer, TBS_bytes);
|
||||
mac_pdu_exist = 1;
|
||||
}
|
||||
}
|
||||
@@ -1087,11 +1081,11 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
|
||||
LOG_I(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 retransmitted\n", frame_tx, slot_tx);
|
||||
// 38.321 restart the ra-ContentionResolutionTimer at each HARQ retransmission in the first symbol after the end of the Msg3
|
||||
// transmission
|
||||
nr_Msg3_transmitted(ul_info->module_id, ul_info->cc_id, ul_info->frame, ul_info->slot, ul_info->gNB_index);
|
||||
nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index);
|
||||
}
|
||||
if (ra->ra_state == WAIT_RAR && !ra->cfra) {
|
||||
LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 transmitted\n", frame_tx, slot_tx);
|
||||
nr_Msg3_transmitted(ul_info->module_id, ul_info->cc_id, frame_tx, slot_tx, ul_info->gNB_index);
|
||||
nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index);
|
||||
}
|
||||
}
|
||||
ulcfg_pdu++;
|
||||
@@ -1101,20 +1095,19 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
|
||||
LOG_D(NR_MAC, "3# scheduled_response transmitted,%d, %d\n", frame_tx, slot_tx);
|
||||
nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slot_tx,
|
||||
.mac = mac,
|
||||
.module_id = ul_info->module_id,
|
||||
.CC_id = ul_info->cc_id,
|
||||
.module_id = mac->ue_id,
|
||||
.CC_id = cc_id,
|
||||
.phy_data = ul_info->phy_data};
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
}
|
||||
|
||||
// update Bj for all active lcids before LCP procedure
|
||||
LOG_D(NR_MAC, "====================[Frame %d][Slot %d]Logical Channel Prioritization===========\n", frame_tx, slot_tx);
|
||||
for (nr_lcordered_info_t *lc_bearer = mac->lc_ordered_info; lc_bearer->logicalChannelConfig_ordered != NULL; lc_bearer++) {
|
||||
int lcid = lc_bearer->lcids_ordered;
|
||||
NR_LogicalChannelConfig_t *lcconfig = mac->logicalChannelConfig[lcid - 1];
|
||||
NR_LC_SCHEDULING_INFO *sched_lc = &mac->scheduling_info.lc_sched_info[lcid - 1];
|
||||
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
|
||||
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
|
||||
int lcid = lc_info->lcid;
|
||||
// max amount of data that can be buffered/accumulated in a logical channel buffer
|
||||
int32_t bucketSize_max = sched_lc->bucket_size;
|
||||
int32_t bucketSize_max = lc_info->bucket_size;
|
||||
AssertFatal(bucketSize_max >= 0, "negative bucketSize_max %d, will never schedule UE: lcid %d\n",bucketSize_max, lcid);
|
||||
|
||||
/*
|
||||
@@ -1122,15 +1115,13 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
|
||||
increment the value of Bj by product PBR * T
|
||||
*/
|
||||
int T = 1; // time elapsed since Bj was last incremented
|
||||
int32_t bj = sched_lc->Bj;
|
||||
bj += nr_get_pbr(lcconfig->ul_SpecificParameters->prioritisedBitRate) * T;
|
||||
if (lcconfig->ul_SpecificParameters->prioritisedBitRate
|
||||
== NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) {
|
||||
bj = nr_get_pbr(lcconfig->ul_SpecificParameters->prioritisedBitRate);
|
||||
}
|
||||
int32_t bj = mac->scheduling_info.lc_sched_info[lcid - 1].Bj;
|
||||
bj += nr_get_pbr(lc_info->prioritisedBitRate) * T;
|
||||
if (lc_info->prioritisedBitRate == NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity)
|
||||
bj = nr_get_pbr(lc_info->prioritisedBitRate);
|
||||
|
||||
// bj > max bucket size, set bj to max bucket size, as in ts38.321 5.4.3.1 Logical Channel Prioritization
|
||||
sched_lc->Bj = min(bj, bucketSize_max);
|
||||
mac->scheduling_info.lc_sched_info[lcid - 1].Bj = min(bj, bucketSize_max);
|
||||
}
|
||||
|
||||
// Call BSR procedure as described in Section 5.4.5 in 38.321
|
||||
@@ -1147,21 +1138,20 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
|
||||
}
|
||||
|
||||
//Check whether Regular BSR is triggered
|
||||
if (nr_update_bsr(mod_id, frame_tx, slot_tx, gNB_index) == true) {
|
||||
if (nr_update_bsr(mac, frame_tx, slot_tx, gNB_index) == true) {
|
||||
// call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp. This should implement the procedures
|
||||
// outlined in Sections 5.4.4 an 5.4.5 of 38.321
|
||||
mac->scheduling_info.SR_pending = 1;
|
||||
// Regular BSR trigger
|
||||
mac->BSR_reporting_active |= NR_BSR_TRIGGER_REGULAR;
|
||||
LOG_D(NR_MAC, "[UE %d][BSR] Regular BSR Triggered Frame %d slot %d SR for PUSCH is pending\n",
|
||||
mod_id, frame_tx, slot_tx);
|
||||
LOG_D(NR_MAC, "[UE %d][BSR] Regular BSR Triggered Frame %d slot %d SR for PUSCH is pending\n", mac->ue_id, frame_tx, slot_tx);
|
||||
}
|
||||
|
||||
if(mac->state >= UE_PERFORMING_RA)
|
||||
nr_ue_pucch_scheduler(mod_id,frame_tx, slot_tx, ul_info->phy_data);
|
||||
nr_ue_pucch_scheduler(mac, frame_tx, slot_tx, ul_info->phy_data);
|
||||
}
|
||||
|
||||
bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index)
|
||||
bool nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index)
|
||||
{
|
||||
bool bsr_regular_triggered = false;
|
||||
uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined
|
||||
@@ -1180,7 +1170,6 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
|
||||
uint8_t array_index = 0;
|
||||
// Reset All BSR Infos
|
||||
lcid_bytes_in_buffer[0] = 0;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
// TO BE NOTED LCID = 0 is excluded from buffers
|
||||
// so they need to be addressed with lcid - 1
|
||||
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) {
|
||||
@@ -1196,56 +1185,61 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
|
||||
}
|
||||
|
||||
//Get Buffer Occupancy and fill lcid_reordered_array
|
||||
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) {
|
||||
if (mac->logicalChannelConfig[lcid - 1] != NULL) { // todo
|
||||
int lcgid = mac->scheduling_info.lc_sched_info[lcid - 1].LCGID;
|
||||
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
|
||||
int lcid = mac->lc_ordered_list.array[i]->lcid;
|
||||
int lcgid = mac->scheduling_info.lc_sched_info[lcid - 1].LCGID;
|
||||
|
||||
// Store already available data to transmit per Group
|
||||
// Store already available data to transmit per Group
|
||||
if (lcgid < NR_MAX_NUM_LCGID) {
|
||||
lcgid_buffer_remain[lcgid] += mac->scheduling_info.lc_sched_info[lcid - 1].LCID_buffer_remain;
|
||||
}
|
||||
|
||||
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mac->ue_id,
|
||||
mac->ue_id,
|
||||
gNB_index,
|
||||
frameP,
|
||||
slotP,
|
||||
ENB_FLAG_NO,
|
||||
MBMS_FLAG_NO,
|
||||
lcid,
|
||||
0,
|
||||
0);
|
||||
|
||||
lcid_bytes_in_buffer[lcid - 1] = rlc_status.bytes_in_buffer;
|
||||
|
||||
if (rlc_status.bytes_in_buffer > 0) {
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d slot %d\n",
|
||||
mac->ue_id,
|
||||
lcid,
|
||||
lcgid,
|
||||
rlc_status.bytes_in_buffer,
|
||||
frameP,
|
||||
slotP);
|
||||
mac->scheduling_info.lc_sched_info[lcid - 1].LCID_status = LCID_NOT_EMPTY;
|
||||
|
||||
//Update BSR_bytes and position in lcid_reordered_array only if Group is defined
|
||||
if (lcgid < NR_MAX_NUM_LCGID) {
|
||||
lcgid_buffer_remain[lcgid] += mac->scheduling_info.lc_sched_info[lcid - 1].LCID_buffer_remain;
|
||||
}
|
||||
num_lcid_with_data ++;
|
||||
// sum lcid buffer which has same lcgid
|
||||
mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes += rlc_status.bytes_in_buffer;
|
||||
//Fill in the array
|
||||
array_index = 0;
|
||||
|
||||
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(module_idP,
|
||||
mac->ue_id,
|
||||
gNB_index,
|
||||
frameP,
|
||||
slotP,
|
||||
ENB_FLAG_NO,
|
||||
MBMS_FLAG_NO,
|
||||
lcid,
|
||||
0,
|
||||
0);
|
||||
|
||||
lcid_bytes_in_buffer[lcid - 1] = rlc_status.bytes_in_buffer;
|
||||
|
||||
if (rlc_status.bytes_in_buffer > 0) {
|
||||
LOG_D(NR_MAC,"[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d slot %d\n",
|
||||
module_idP, lcid,lcgid,rlc_status.bytes_in_buffer,frameP,slotP);
|
||||
mac->scheduling_info.lc_sched_info[lcid - 1].LCID_status = LCID_NOT_EMPTY;
|
||||
|
||||
//Update BSR_bytes and position in lcid_reordered_array only if Group is defined
|
||||
if (lcgid < NR_MAX_NUM_LCGID) {
|
||||
num_lcid_with_data ++;
|
||||
// sum lcid buffer which has same lcgid
|
||||
mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes += rlc_status.bytes_in_buffer;
|
||||
//Fill in the array
|
||||
array_index = 0;
|
||||
|
||||
do {
|
||||
//if (mac->logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority) {
|
||||
if (1) { // todo
|
||||
//Insert if priority is higher or equal (lower or equal in value)
|
||||
for (pos_next = num_lcid_with_data - 1; pos_next > array_index; pos_next--) {
|
||||
lcid_reordered_array[pos_next] = lcid_reordered_array[pos_next - 1];
|
||||
}
|
||||
|
||||
lcid_reordered_array[array_index] = lcid;
|
||||
break;
|
||||
do {
|
||||
//if (mac->logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority) {
|
||||
if (1) { // todo
|
||||
//Insert if priority is higher or equal (lower or equal in value)
|
||||
for (pos_next = num_lcid_with_data - 1; pos_next > array_index; pos_next--) {
|
||||
lcid_reordered_array[pos_next] = lcid_reordered_array[pos_next - 1];
|
||||
}
|
||||
|
||||
array_index ++;
|
||||
} while ((array_index < num_lcid_with_data) && (array_index <= NR_MAX_NUM_LCID));
|
||||
}
|
||||
lcid_reordered_array[array_index] = lcid;
|
||||
break;
|
||||
}
|
||||
|
||||
array_index ++;
|
||||
} while ((array_index < num_lcid_with_data) && (array_index <= NR_MAX_NUM_LCID));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1253,8 +1247,12 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
|
||||
// Check whether a regular BSR can be triggered according to the first cases in 38.321
|
||||
if (num_lcid_with_data) {
|
||||
LOG_D(NR_MAC, "[UE %d] PDCCH Tick at frame %d slot %d: NumLCID with data=%d Reordered LCID0=%d LCID1=%d LCID2=%d\n",
|
||||
module_idP, frameP, slotP, num_lcid_with_data,
|
||||
lcid_reordered_array[0], lcid_reordered_array[1],
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
slotP,
|
||||
num_lcid_with_data,
|
||||
lcid_reordered_array[0],
|
||||
lcid_reordered_array[1],
|
||||
lcid_reordered_array[2]);
|
||||
|
||||
for (array_index = 0; array_index < num_lcid_with_data; array_index++) {
|
||||
@@ -1267,8 +1265,8 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
|
||||
{
|
||||
bsr_regular_triggered = true;
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d slot %d\n",
|
||||
module_idP,
|
||||
"[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%ld data become available at frame %d slot %d\n",
|
||||
mac->ue_id,
|
||||
lcid,
|
||||
mac->scheduling_info.lc_sched_info[lcid - 1].LCGID,
|
||||
frameP,
|
||||
@@ -1282,8 +1280,7 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
|
||||
bsr_regular_triggered = true;
|
||||
|
||||
if ((mac->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0) {
|
||||
LOG_I(NR_MAC, "[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d slot %d\n",
|
||||
module_idP, frameP, slotP);
|
||||
LOG_I(NR_MAC, "[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d slot %d\n", mac->ue_id, frameP, slotP);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1296,8 +1293,8 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
|
||||
return bsr_regular_triggered;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int value) {
|
||||
uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int value)
|
||||
{
|
||||
uint8_t ju, jm, jl;
|
||||
int ascend;
|
||||
//DevAssert(size > 0);
|
||||
@@ -2121,9 +2118,8 @@ void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac)
|
||||
LOG_D(NR_MAC,"Map SSB to RO done\n");
|
||||
}
|
||||
|
||||
void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, void *phy_data)
|
||||
void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP, void *phy_data)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
PUCCH_sched_t pucch[3] = {0}; // TODO the size might change in the future in case of multiple SR or multiple CSI in a slot
|
||||
|
||||
mac->nr_ue_emul_l1.num_srs = 0;
|
||||
@@ -2135,7 +2131,7 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, vo
|
||||
if (mac->state == UE_CONNECTED && trigger_periodic_scheduling_request(mac, &pucch[0], frameP, slotP)) {
|
||||
num_res++;
|
||||
/* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */
|
||||
pucch[0].sr_payload = nr_ue_get_SR(module_idP, frameP, slotP);
|
||||
pucch[0].sr_payload = nr_ue_get_SR(mac, frameP, slotP);
|
||||
}
|
||||
|
||||
// CSI
|
||||
@@ -2189,7 +2185,7 @@ void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, vo
|
||||
if (mac->if_module != NULL && mac->if_module->scheduled_response != NULL) {
|
||||
nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slotP,
|
||||
.mac = mac,
|
||||
.module_id = module_idP,
|
||||
.module_id = mac->ue_id,
|
||||
.CC_id = 0 /*TBR fix*/,
|
||||
.phy_data = phy_data};
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
@@ -2482,9 +2478,8 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot)
|
||||
// PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
|
||||
// - todo:
|
||||
// - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config
|
||||
static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
|
||||
static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_frame_t slotP)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
RA_config_t *ra = &mac->ra;
|
||||
ra->RA_offset = 2; // to compensate the rx frame offset at the gNB
|
||||
if(ra->ra_state != GENERATE_PREAMBLE)
|
||||
@@ -2609,19 +2604,19 @@ static void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_fr
|
||||
}
|
||||
} // if format1
|
||||
|
||||
nr_get_prach_resources(module_idP, 0, 0, &ra->prach_resources, ra->rach_ConfigDedicated);
|
||||
nr_get_prach_resources(mac, 0, 0, &ra->prach_resources, ra->rach_ConfigDedicated);
|
||||
pdu->prach_config_pdu.ra_PreambleIndex = ra->ra_PreambleIndex;
|
||||
pdu->prach_config_pdu.prach_tx_power = get_prach_tx_power(module_idP);
|
||||
pdu->prach_config_pdu.prach_tx_power = get_prach_tx_power(mac);
|
||||
set_ra_rnti(mac, &pdu->prach_config_pdu);
|
||||
release_ul_config(pdu, false);
|
||||
nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slotP,
|
||||
.mac = mac,
|
||||
.module_id = module_idP,
|
||||
.module_id = mac->ue_id,
|
||||
.CC_id = 0 /*TBR fix*/};
|
||||
if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
|
||||
mac->if_module->scheduled_response(&scheduled_response);
|
||||
|
||||
nr_Msg1_transmitted(module_idP);
|
||||
nr_Msg1_transmitted(mac);
|
||||
} // is_nr_prach_slot
|
||||
} // if is_nr_UL_slot
|
||||
}
|
||||
@@ -2653,17 +2648,15 @@ typedef struct {
|
||||
phr_ce_len; TBD
|
||||
phr_header_len; TBD
|
||||
*/
|
||||
int nr_ue_get_sdu_mac_ce_pre(module_id_t module_idP,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframe,
|
||||
uint8_t gNB_index,
|
||||
uint8_t *ulsch_buffer,
|
||||
uint16_t buflen,
|
||||
NR_UE_MAC_CE_INFO *mac_ce_p)
|
||||
static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframe,
|
||||
uint8_t gNB_index,
|
||||
uint8_t *ulsch_buffer,
|
||||
uint16_t buflen,
|
||||
NR_UE_MAC_CE_INFO *mac_ce_p)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
|
||||
int num_lcg_id_with_data = 0;
|
||||
// Preparing the MAC CEs sub-PDUs and get the total size
|
||||
mac_ce_p->bsr_header_len = 0;
|
||||
@@ -2689,7 +2682,7 @@ int nr_ue_get_sdu_mac_ce_pre(module_id_t module_idP,
|
||||
mac->BSR_reporting_active |= NR_BSR_TRIGGER_PERIODIC;
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n",
|
||||
module_idP,
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
subframe,
|
||||
buflen);
|
||||
@@ -2737,17 +2730,15 @@ int nr_ue_get_sdu_mac_ce_pre(module_id_t module_idP,
|
||||
bsr_l
|
||||
bsr_t
|
||||
*/
|
||||
void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframe,
|
||||
uint8_t gNB_index,
|
||||
uint8_t *ulsch_buffer,
|
||||
uint16_t buflen,
|
||||
NR_UE_MAC_CE_INFO *mac_ce_p)
|
||||
static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframe,
|
||||
uint8_t gNB_index,
|
||||
uint8_t *ulsch_buffer,
|
||||
uint16_t buflen,
|
||||
NR_UE_MAC_CE_INFO *mac_ce_p)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
|
||||
// Compute BSR Values and update Nb LCGID with data after multiplexing
|
||||
unsigned short padding_len = 0;
|
||||
int lcg_id = 0;
|
||||
@@ -2839,7 +2830,7 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %d] Frame %d subframe %d BSR Trig=%d report LONG BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 "
|
||||
"%d level LCGID4 %d,level LCGID5 %d,level LCGID6 %d,level LCGID7 %d)\n",
|
||||
module_idP,
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
subframe,
|
||||
mac->BSR_reporting_active,
|
||||
@@ -2861,7 +2852,7 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
|
||||
mac_ce_p->bsr_t->Buffer_size = mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR;
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n",
|
||||
module_idP,
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
subframe,
|
||||
mac->BSR_reporting_active,
|
||||
@@ -2873,7 +2864,7 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
|
||||
mac_ce_p->bsr_s->Buffer_size = mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR;
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n",
|
||||
module_idP,
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
subframe,
|
||||
mac->BSR_reporting_active,
|
||||
@@ -2882,7 +2873,7 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(NR_MAC, "[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n", module_idP);
|
||||
LOG_D(NR_MAC, "[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n", mac->ue_id);
|
||||
mac->scheduling_info.SR_pending = 0;
|
||||
mac->scheduling_info.SR_COUNTER = 0;
|
||||
|
||||
@@ -2890,18 +2881,18 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
|
||||
if (mac_ce_p->bsr_ce_len) {
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %d] MAC BSR Sent !! bsr (ce%d,hdr%d) buff_len %d\n",
|
||||
module_idP,
|
||||
mac->ue_id,
|
||||
mac_ce_p->bsr_ce_len,
|
||||
mac_ce_p->bsr_header_len,
|
||||
buflen);
|
||||
// Reset ReTx BSR Timer
|
||||
mac->scheduling_info.retxBSR_SF = nr_get_sf_retxBSRTimer(mac->scheduling_info.retxBSR_Timer);
|
||||
LOG_D(NR_MAC, "[UE %d] MAC ReTx BSR Timer Reset =%d\n", module_idP, mac->scheduling_info.retxBSR_SF);
|
||||
LOG_D(NR_MAC, "[UE %d] MAC ReTx BSR Timer Reset =%d\n", mac->ue_id, mac->scheduling_info.retxBSR_SF);
|
||||
|
||||
// Reset Periodic Timer except when BSR is truncated
|
||||
if ((mac_ce_p->bsr_t == NULL) && (mac->scheduling_info.periodicBSR_Timer != NR_BSR_Config__periodicBSR_Timer_infinity)) {
|
||||
mac->scheduling_info.periodicBSR_SF = nr_get_sf_periodicBSRTimer(mac->scheduling_info.periodicBSR_Timer);
|
||||
LOG_D(NR_MAC, "[UE %d] MAC Periodic BSR Timer Reset =%d\n", module_idP, mac->scheduling_info.periodicBSR_SF);
|
||||
LOG_D(NR_MAC, "[UE %d] MAC Periodic BSR Timer Reset =%d\n", mac->ue_id, mac->scheduling_info.periodicBSR_SF);
|
||||
}
|
||||
|
||||
// Reset BSR Trigger flags
|
||||
@@ -2909,16 +2900,13 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t get_count_lcids_same_priority(NR_UE_MAC_INST_t *mac, uint8_t start, uint8_t total_active_lcids, int *lcid_ordered_array)
|
||||
uint32_t get_count_lcids_same_priority(uint8_t start, uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array)
|
||||
{
|
||||
// count number of logical channels with same priority as curr_lcid
|
||||
uint8_t same_priority_count = 0;
|
||||
uint8_t curr_lcid = lcid_ordered_array[start];
|
||||
NR_LogicalChannelConfig_t *lc_config_curr = mac->logicalChannelConfig[curr_lcid - 1];
|
||||
uint8_t curr_lcid = lcid_ordered_array[start].lcid;
|
||||
for (uint8_t index = start; index < total_active_lcids; index++) {
|
||||
uint8_t next_lcid = lcid_ordered_array[index];
|
||||
NR_LogicalChannelConfig_t *lc_config_next = mac->logicalChannelConfig[next_lcid - 1];
|
||||
if (lc_config_curr->ul_SpecificParameters->priority == lc_config_next->ul_SpecificParameters->priority) {
|
||||
if (lcid_ordered_array[start].priority == lcid_ordered_array[index].priority) {
|
||||
same_priority_count++;
|
||||
}
|
||||
}
|
||||
@@ -2936,8 +2924,15 @@ long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
|
||||
long *target)
|
||||
{
|
||||
/* Calculates the number of bytes the logical channel should request from the correcponding RLC buffer*/
|
||||
NR_LogicalChannelConfig_t *lc_config = mac->logicalChannelConfig[lc_num - 1];
|
||||
long pbr = nr_get_pbr(lc_config->ul_SpecificParameters->prioritisedBitRate);
|
||||
long found_pbr = -1;
|
||||
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
|
||||
if (mac->lc_ordered_list.array[i]->lcid == lc_num) {
|
||||
found_pbr = mac->lc_ordered_list.array[i]->prioritisedBitRate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AssertFatal(found_pbr >= 0, "Couldn't find LC config for ID %d\n", lc_num);
|
||||
uint32_t pbr = nr_get_pbr(found_pbr);
|
||||
int32_t lcid_remain_buffer = mac->scheduling_info.lc_sched_info[lc_num - 1].LCID_buffer_remain;
|
||||
*target = (same_priority_count > 1) ? min(buflen_remain_ep, pbr) : pbr;
|
||||
|
||||
@@ -2963,11 +2958,11 @@ long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
|
||||
return num_bytes_requested;
|
||||
}
|
||||
|
||||
bool get_dataavailability_buffers(uint8_t total_active_lcids, int *lcid_ordered_array, bool *data_status_lcbuffers)
|
||||
bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array, bool *data_status_lcbuffers)
|
||||
{
|
||||
// check whether there is any data in the rlc buffer corresponding to active lcs
|
||||
for (uint8_t id = 0; id < total_active_lcids; id++) {
|
||||
int lcid = lcid_ordered_array[id];
|
||||
int lcid = lcid_ordered_array[id].lcid;
|
||||
if (data_status_lcbuffers[lcid - 1]) {
|
||||
return true;
|
||||
}
|
||||
@@ -2975,24 +2970,23 @@ bool get_dataavailability_buffers(uint8_t total_active_lcids, int *lcid_ordered_
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t select_logical_channels(NR_UE_MAC_INST_t *mac, uint8_t *num_active_lcids, int *active_lcids)
|
||||
static void select_logical_channels(NR_UE_MAC_INST_t *mac, int *num_active_lcids, nr_lcordered_info_t *active_lcids)
|
||||
{
|
||||
// (TODO: selection of logical channels for logical channel prioritization procedure as per 5.4.3.1.2 Selection of logical
|
||||
// channels, TS38.321)
|
||||
|
||||
// selection of logical channels with Bj > 0
|
||||
for (nr_lcordered_info_t *lc_bearer = mac->lc_ordered_info; lc_bearer->logicalChannelConfig_ordered != NULL; lc_bearer++) {
|
||||
uint8_t lcid = lc_bearer->lcids_ordered;
|
||||
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
|
||||
int lcid = mac->lc_ordered_list.array[i]->lcid;
|
||||
if (mac->scheduling_info.lc_sched_info[lcid - 1].Bj > 0) {
|
||||
active_lcids[*num_active_lcids] = lcid;
|
||||
active_lcids[*num_active_lcids] = *mac->lc_ordered_list.array[i];
|
||||
(*num_active_lcids)++;
|
||||
LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, *num_active_lcids);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool fill_mac_sdu(module_id_t module_idP,
|
||||
static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframe,
|
||||
uint8_t gNB_index,
|
||||
@@ -3009,16 +3003,14 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
bool *lcids_data_status,
|
||||
uint8_t *num_lcids_same_priority)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info;
|
||||
const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG);
|
||||
|
||||
/* prepare the MAC sdu */
|
||||
int32_t lcid_remain_buffer = sched_info->lc_sched_info[lcid - 1].LCID_buffer_remain;
|
||||
LOG_D(NR_MAC,
|
||||
"In %s: [UE %d] [%d.%d] lcp round = %d, remaining mac pdu length = %d, lcid buffer remaining = %d, lcid = %d \n",
|
||||
__FUNCTION__,
|
||||
module_idP,
|
||||
"[UE %d] [%d.%d] lcp round = %d, remaining mac pdu length = %d, lcid buffer remaining = %d, lcid = %d \n",
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
subframe,
|
||||
*counter,
|
||||
@@ -3036,7 +3028,7 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
long bytes_requested =
|
||||
get_num_bytes_to_reqlc(mac, count_same_priority_lcids, lcid, buflen_ep, *buflen_remain, *counter, lcids_bytes_tot, &target);
|
||||
|
||||
uint16_t sdu_length = mac_rlc_data_req(module_idP,
|
||||
uint16_t sdu_length = mac_rlc_data_req(mac->ue_id,
|
||||
mac->ue_id,
|
||||
gNB_index,
|
||||
frameP,
|
||||
@@ -3049,8 +3041,7 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
0);
|
||||
|
||||
AssertFatal(bytes_requested >= sdu_length,
|
||||
"In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %li remaining bytes\n",
|
||||
__FUNCTION__,
|
||||
"LCID = 0x%02x RLC has segmented %d bytes but MAC has max %li remaining bytes\n",
|
||||
lcid,
|
||||
sdu_length,
|
||||
bytes_requested);
|
||||
@@ -3059,7 +3050,7 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
// currently the Bj is drecremented by size of MAC SDus everytime it is served to logical channel, so by this approach there
|
||||
// will be more chance for lower priority logical channels to be served in the next TTI
|
||||
// second approach can also be followed where Bj is decremented only in the first round but not in the subsequent rounds
|
||||
sched_info->lc_sched_info[lcid - 1].Bj -= sdu_length;
|
||||
sched_info->lc_sched_info[lcid - 1].Bj -= sdu_length; // TODO avoid Bj to go below 0
|
||||
LOG_D(NR_MAC,
|
||||
"decrement Bj of the lcid %d by size of sdu length = %d and new Bj for lcid %d is %d\n",
|
||||
lcid,
|
||||
@@ -3069,10 +3060,9 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
|
||||
if (sdu_length > 0) {
|
||||
LOG_D(NR_MAC,
|
||||
"In %s: [UE %d] [%d.%d] UL-DXCH -> ULSCH, Generating UL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID "
|
||||
"[UE %d] [%d.%d] UL-DXCH -> ULSCH, Generating UL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID "
|
||||
"0x%02x (buflen (TBS) %d bytes)\n",
|
||||
__FUNCTION__,
|
||||
module_idP,
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
subframe,
|
||||
(*num_sdus) + 1,
|
||||
@@ -3086,9 +3076,9 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
header->L = htons(sdu_length);
|
||||
|
||||
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
|
||||
LOG_I(NR_MAC, "In %s: dumping MAC sub-header with length %d: \n", __FUNCTION__, sh_size);
|
||||
LOG_I(NR_MAC, "dumping MAC sub-header with length %d: \n", sh_size);
|
||||
log_dump(NR_MAC, header, sh_size, LOG_DUMP_CHAR, "\n");
|
||||
LOG_I(NR_MAC, "In %s: dumping MAC SDU with length %d \n", __FUNCTION__, sdu_length);
|
||||
LOG_I(NR_MAC, "dumping MAC SDU with length %d \n", sdu_length);
|
||||
log_dump(NR_MAC, *pdu, sdu_length, LOG_DUMP_CHAR, "\n");
|
||||
#endif
|
||||
|
||||
@@ -3101,7 +3091,7 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
*pdu -= sh_size;
|
||||
lcids_data_status[lcid - 1] = false;
|
||||
(*num_lcids_same_priority)--;
|
||||
LOG_D(NR_MAC, "In %s: no data to transmit for RB with LCID 0x%02x\n and hence set to false", __FUNCTION__, lcid);
|
||||
LOG_D(NR_MAC, "No data to transmit for RB with LCID 0x%02x\n and hence set to false", lcid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3113,8 +3103,8 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
lc_info->LCID_buffer_remain -= sdu_length;
|
||||
(lcg_info + lc_info->LCGID)->BSR_bytes -= sdu_length;
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %d] Update BSR [%d.%d] BSR_bytes for LCG%d = %d\n",
|
||||
module_idP,
|
||||
"[UE %d] Update BSR [%d.%d] BSR_bytes for LCG%ld = %d\n",
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
subframe,
|
||||
lc_info->LCGID,
|
||||
@@ -3130,8 +3120,7 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
&& lcids_bytes_tot[lcid - 1] >= buflen_ep)) { // only prioritized bit rate should be taken from logical channel in
|
||||
// the first lcp run except when infinity
|
||||
LOG_D(NR_MAC,
|
||||
"In %s: total number bytes read from rlc buffer for lcid %d are %d\n",
|
||||
__FUNCTION__,
|
||||
"Total number bytes read from rlc buffer for lcid %d are %d\n",
|
||||
lcid,
|
||||
lcids_bytes_tot[lcid - 1]);
|
||||
(*num_lcids_same_priority)--;
|
||||
@@ -3152,7 +3141,7 @@ static bool fill_mac_sdu(module_id_t module_idP,
|
||||
* @ulsch_buffer Pointer to ULSCH PDU
|
||||
* @buflen TBS
|
||||
*/
|
||||
uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
|
||||
int CC_id,
|
||||
frame_t frameP,
|
||||
sub_frame_t subframe,
|
||||
@@ -3179,7 +3168,6 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
mac_ce_p->bsr_t = &bsr_truncated;
|
||||
//NR_POWER_HEADROOM_CMD phr;
|
||||
//mac_ce_p->phr_p = &phr;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
|
||||
|
||||
NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info;
|
||||
//int highest_priority = 16;
|
||||
@@ -3188,10 +3176,6 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
// Pointer used to build the MAC PDU by placing the RLC SDUs in the ULSCH buffer
|
||||
uint8_t *pdu = ulsch_buffer;
|
||||
|
||||
// variable used to build the lcids with positive Bj
|
||||
int lcids_bj_pos[NR_MAX_NUM_LCID] = {0};
|
||||
uint8_t avail_lcids_count = 0;
|
||||
|
||||
// variable used to store the lcid data status during lcp
|
||||
bool lcids_data_status[NR_MAX_NUM_LCID] = {0};
|
||||
memset(lcids_data_status, 1, NR_MAX_NUM_LCID);
|
||||
@@ -3203,12 +3187,15 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
// because as per standard(TS38.321), all equal priority channels should be served equally
|
||||
|
||||
// nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length
|
||||
mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(module_idP, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p);
|
||||
mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(mac, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p);
|
||||
mac_ce_p->total_mac_pdu_header_len = mac_ce_p->tot_mac_ce_len;
|
||||
|
||||
LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", __FUNCTION__, module_idP, frameP, subframe, buflen);
|
||||
LOG_D(NR_MAC, "[UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", mac->ue_id, frameP, subframe, buflen);
|
||||
|
||||
// selection of logical channels
|
||||
int avail_lcids_count = 0;
|
||||
// variable used to build the lcids with positive Bj
|
||||
nr_lcordered_info_t lcids_bj_pos[mac->lc_ordered_list.count];
|
||||
select_logical_channels(mac, &avail_lcids_count, lcids_bj_pos);
|
||||
|
||||
// multiplex in the order of highest priority
|
||||
@@ -3229,7 +3216,7 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
still space availble in the MAC PDU, then from the next run all the remaining data from the higher priority logical channel
|
||||
is placed in the MAC PDU before going on to next high priority logical channel
|
||||
*/
|
||||
int lcid = lcids_bj_pos[id];
|
||||
int lcid = lcids_bj_pos[id].lcid;
|
||||
|
||||
// skip the logical channel if no data in the buffer initially or the data in the buffer was zero because it was written in to
|
||||
// MAC PDU
|
||||
@@ -3241,17 +3228,16 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
// count number of lc with same priority as lcid
|
||||
if (!num_lcids_same_priority) {
|
||||
num_lcids_same_priority = count_same_priority_lcids =
|
||||
get_count_lcids_same_priority(mac, id, avail_lcids_count, lcids_bj_pos);
|
||||
get_count_lcids_same_priority(id, avail_lcids_count, lcids_bj_pos);
|
||||
}
|
||||
|
||||
buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size);
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"In %s: [UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x (TBS %d bytes, sdu_length_total %d bytes, MAC header "
|
||||
"[UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x (TBS %d bytes, sdu_length_total %d bytes, MAC header "
|
||||
"len %d bytes,"
|
||||
"buflen_remain %d bytes)\n",
|
||||
__FUNCTION__,
|
||||
module_idP,
|
||||
mac->ue_id,
|
||||
frameP,
|
||||
subframe,
|
||||
lcid,
|
||||
@@ -3271,7 +3257,7 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
active logical channels in the order of priority are placed in the MAC PDU. The 'get_num_bytes_to_reqlc' calculates
|
||||
the target number of bytes to request from RLC via 'mac_rlc_data_req'
|
||||
*/
|
||||
if (!fill_mac_sdu(module_idP,
|
||||
if (!fill_mac_sdu(mac,
|
||||
frameP,
|
||||
subframe,
|
||||
gNB_index,
|
||||
@@ -3297,7 +3283,7 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
|
||||
|
||||
//nr_ue_get_sdu_mac_ce_post recalculates all mac_ce related header fields since buffer has been changed after mac_rlc_data_req.
|
||||
//Also, BSR padding is handled here after knowing mac_ce_p->sdu_length_total.
|
||||
nr_ue_get_sdu_mac_ce_post(module_idP, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p);
|
||||
nr_ue_get_sdu_mac_ce_post(mac, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p);
|
||||
|
||||
if (mac_ce_p->tot_mac_ce_len > 0) {
|
||||
|
||||
@@ -3361,7 +3347,7 @@ void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIG
|
||||
ul_time_alignment->ta_apply = false;
|
||||
}
|
||||
|
||||
uint32_t nr_get_pbr(uint8_t prioritizedbitrate)
|
||||
uint32_t nr_get_pbr(long prioritizedbitrate)
|
||||
{
|
||||
int32_t pbr = -1;
|
||||
switch (prioritizedbitrate) {
|
||||
|
||||
@@ -358,8 +358,20 @@ static uint32_t schedule_control_sib1(module_id_t module_id,
|
||||
rbSize, tda_info->nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3;
|
||||
} while (TBS < gNB_mac->sched_ctrlCommon->num_total_bytes);
|
||||
|
||||
AssertFatal(TBS>=gNB_mac->sched_ctrlCommon->num_total_bytes,"Couldn't allocate enough resources for %d bytes in SIB1 PDSCH\n",
|
||||
gNB_mac->sched_ctrlCommon->num_total_bytes);
|
||||
if (TBS < gNB_mac->sched_ctrlCommon->num_total_bytes) {
|
||||
for (int rb = 0; rb < bwpSize; rb++)
|
||||
LOG_I(NR_MAC, "vrb_map[%d] %x\n", rbStart + rb, vrb_map[rbStart + rb]);
|
||||
}
|
||||
AssertFatal(
|
||||
TBS >= gNB_mac->sched_ctrlCommon->num_total_bytes,
|
||||
"Couldn't allocate enough resources for %d bytes in SIB1 PDSCH (rbStart %d, rbSize %d, bwpSize %d SLmask %x - [%d,%d])\n",
|
||||
gNB_mac->sched_ctrlCommon->num_total_bytes,
|
||||
rbStart,
|
||||
rbSize,
|
||||
bwpSize,
|
||||
SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols),
|
||||
tda_info->startSymbolIndex,
|
||||
tda_info->nrOfSymbols);
|
||||
|
||||
pdsch->rbSize = rbSize;
|
||||
pdsch->rbStart = 0;
|
||||
|
||||
@@ -185,7 +185,16 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac,
|
||||
NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index];
|
||||
if (!curr_pucch->active)
|
||||
continue;
|
||||
DevAssert(frameP == curr_pucch->frame && slotP == curr_pucch->ul_slot);
|
||||
if (frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) {
|
||||
LOG_E(NR_MAC,
|
||||
"PUCCH frame/slot mismatch: current %4d.%2d vs. request %4d.%2d: not scheduling PUCCH\n",
|
||||
curr_pucch->frame,
|
||||
curr_pucch->ul_slot,
|
||||
frameP,
|
||||
slotP);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));;
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint16_t O_ack = curr_pucch->dai_c;
|
||||
const uint16_t O_csi = curr_pucch->csi_bits;
|
||||
@@ -1296,8 +1305,13 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
return pucch_index; // index of current PUCCH structure
|
||||
}
|
||||
else if (curr_pucch->active) {
|
||||
AssertFatal(1==0, "This shouldn't happen! curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n",
|
||||
curr_pucch->frame, curr_pucch->ul_slot, pucch_frame, pucch_slot);
|
||||
LOG_E(NR_MAC,
|
||||
"current PUCCH inactive: curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n",
|
||||
curr_pucch->frame,
|
||||
curr_pucch->ul_slot,
|
||||
pucch_frame,
|
||||
pucch_slot);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
else { // unoccupied occasion
|
||||
// checking if in ul_slot the resources potentially to be assigned to this PUCCH are available
|
||||
@@ -1392,8 +1406,13 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
|
||||
curr_pucch->resource_indicator == idx)
|
||||
curr_pucch->sr_flag = true;
|
||||
else if (curr_pucch->active) {
|
||||
AssertFatal(1==0, "This shouldn't happen! curr_pucch frame.slot %d.%d not matching with SR function frame.slot %d.%d\n",
|
||||
curr_pucch->frame, curr_pucch->ul_slot, SFN, slot);
|
||||
LOG_E(NR_MAC,
|
||||
"current PUCCH inactive: curr_pucch frame.slot %d.%d not matching with computed frame.slot %d.%d\n",
|
||||
curr_pucch->frame,
|
||||
curr_pucch->ul_slot,
|
||||
SFN,
|
||||
slot);
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -385,12 +385,49 @@ static void match_crc_rx_pdu(nfapi_nr_rx_data_indication_t *rx_ind, nfapi_nr_crc
|
||||
}
|
||||
}
|
||||
|
||||
static void run_scheduler(module_id_t module_id, int CC_id, int frame, int slot)
|
||||
{
|
||||
NR_IF_Module_t *ifi = nr_if_inst[module_id];
|
||||
// gNB_MAC_INST *mac = RC.nrmac[module_id];
|
||||
|
||||
NR_Sched_Rsp_t *sched_info;
|
||||
LOG_D(NR_MAC, "Calling scheduler for %d.%d\n", frame, slot);
|
||||
sched_info = allocate_sched_response();
|
||||
|
||||
// clear UL DCI prior to handling ULSCH
|
||||
sched_info->UL_dci_req.numPdus = 0;
|
||||
gNB_dlsch_ulsch_scheduler(module_id, frame, slot, sched_info);
|
||||
ifi->CC_mask = 0;
|
||||
sched_info->module_id = module_id;
|
||||
sched_info->CC_id = CC_id;
|
||||
sched_info->frame = frame;
|
||||
sched_info->slot = slot;
|
||||
/*
|
||||
sched_info->DL_req = &mac->DL_req[CC_id];
|
||||
sched_info->UL_dci_req = &mac->UL_dci_req[CC_id];
|
||||
|
||||
sched_info->UL_tti_req = mac->UL_tti_req[CC_id];
|
||||
|
||||
sched_info->TX_req = &mac->TX_req[CC_id];
|
||||
*/
|
||||
#ifdef DUMP_FAPI
|
||||
dump_dl(sched_info);
|
||||
#endif
|
||||
|
||||
AssertFatal(ifi->NR_Schedule_response != NULL, "nr_schedule_response is null (mod %d, cc %d)\n", module_id, CC_id);
|
||||
ifi->NR_Schedule_response(sched_info);
|
||||
|
||||
LOG_D(NR_PHY,
|
||||
"NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n",
|
||||
sched_info->frame,
|
||||
sched_info->slot,
|
||||
sched_info->DL_req.dl_tti_request_body.nPDUs);
|
||||
}
|
||||
|
||||
void NR_UL_indication(NR_UL_IND_t *UL_info) {
|
||||
AssertFatal(UL_info!=NULL,"UL_info is null\n");
|
||||
module_id_t module_id = UL_info->module_id;
|
||||
int CC_id = UL_info->CC_id;
|
||||
NR_Sched_Rsp_t *sched_info;
|
||||
NR_IF_Module_t *ifi = nr_if_inst[module_id];
|
||||
module_id_t module_id = UL_info->module_id;
|
||||
int CC_id = UL_info->CC_id;
|
||||
|
||||
LOG_D(NR_PHY,"SFN/SLOT:%d.%d module_id:%d CC_id:%d UL_info[rach_pdus:%zu rx_ind:%zu crcs:%zu]\n",
|
||||
UL_info->frame, UL_info->slot,
|
||||
@@ -449,57 +486,6 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) {
|
||||
if (get_softmodem_params()->emulate_l1) {
|
||||
free_unqueued_nfapi_indications(rach_ind, uci_ind, rx_ind, crc_ind);
|
||||
}
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
gNB_MAC_INST *mac = RC.nrmac[module_id];
|
||||
if (ifi->CC_mask==0) {
|
||||
ifi->current_frame = UL_info->frame;
|
||||
ifi->current_slot = UL_info->slot;
|
||||
} else {
|
||||
AssertFatal(UL_info->frame != ifi->current_frame,"CC_mask %x is not full and frame has changed\n",ifi->CC_mask);
|
||||
AssertFatal(UL_info->slot != ifi->current_slot,"CC_mask %x is not full and slot has changed\n",ifi->CC_mask);
|
||||
}
|
||||
|
||||
ifi->CC_mask |= (1<<CC_id);
|
||||
|
||||
if (ifi->CC_mask == ((1<<MAX_NUM_CCs)-1)) {
|
||||
/*
|
||||
eNB_dlsch_ulsch_scheduler(module_id,
|
||||
(UL_info->frame+((UL_info->slot>(9-sl_ahead))?1:0)) % 1024,
|
||||
(UL_info->slot+sl_ahead)%10);
|
||||
*/
|
||||
nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id];
|
||||
int spf = get_spf(cfg);
|
||||
sched_info = allocate_sched_response();
|
||||
// clear UL DCI prior to handling ULSCH
|
||||
sched_info->UL_dci_req.numPdus = 0;
|
||||
gNB_dlsch_ulsch_scheduler(module_id,
|
||||
(UL_info->frame + ((UL_info->slot > (spf - 1 - ifi->sl_ahead)) ? 1 : 0)) % 1024,
|
||||
(UL_info->slot + ifi->sl_ahead) % spf,
|
||||
sched_info);
|
||||
|
||||
ifi->CC_mask = 0;
|
||||
sched_info->module_id = module_id;
|
||||
sched_info->CC_id = CC_id;
|
||||
sched_info->frame = (UL_info->frame + ((UL_info->slot>(spf-1-ifi->sl_ahead)) ? 1 : 0)) % 1024;
|
||||
sched_info->slot = (UL_info->slot+ifi->sl_ahead)%spf;
|
||||
|
||||
#ifdef DUMP_FAPI
|
||||
dump_dl(sched_info);
|
||||
#endif
|
||||
|
||||
AssertFatal(ifi->NR_Schedule_response!=NULL,
|
||||
"nr_schedule_response is null (mod %d, cc %d)\n",
|
||||
module_id,
|
||||
CC_id);
|
||||
ifi->NR_Schedule_response(sched_info);
|
||||
|
||||
LOG_D(NR_PHY,
|
||||
"NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n",
|
||||
sched_info->frame,
|
||||
sched_info->slot,
|
||||
sched_info->DL_req.dl_tti_request_body.nPDUs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {
|
||||
@@ -514,6 +500,7 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {
|
||||
|
||||
nr_if_inst[Mod_id]->CC_mask=0;
|
||||
nr_if_inst[Mod_id]->NR_UL_indication = NR_UL_indication;
|
||||
nr_if_inst[Mod_id]->NR_slot_indication = run_scheduler;
|
||||
AssertFatal(pthread_mutex_init(&nr_if_inst[Mod_id]->if_mutex,NULL)==0,
|
||||
"allocation of nr_if_inst[%d]->if_mutex fails\n",Mod_id);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ typedef struct NR_IF_Module_s {
|
||||
//define the function pointer
|
||||
void (*NR_UL_indication)(NR_UL_IND_t *UL_INFO);
|
||||
void (*NR_Schedule_response)(NR_Sched_Rsp_t *Sched_INFO);
|
||||
void (*NR_slot_indication)(module_id_t module_idP, int CC_id, int frame, int slot);
|
||||
void (*NR_PHY_config_req)(NR_PHY_Config_t *config_INFO);
|
||||
uint32_t CC_mask;
|
||||
uint16_t current_frame;
|
||||
|
||||
@@ -105,6 +105,7 @@ NR_Sched_Rsp_t *allocate_sched_response(void)
|
||||
|
||||
static void release_sched_response(int sched_response_id)
|
||||
{
|
||||
LOG_D(NR_MAC,"Releasing sched_response %d\n",sched_response_id);
|
||||
resp_freelist_next[sched_response_id] = resp_freelist_head;
|
||||
resp_freelist_head = sched_response_id;
|
||||
}
|
||||
@@ -124,6 +125,7 @@ void deref_sched_response(int sched_response_id)
|
||||
AssertFatal(resp_freelist_inited, "sched_response used before init\n");
|
||||
AssertFatal(resp_refcount[sched_response_id] > 0, "sched_reponse decreased too much\n");
|
||||
|
||||
LOG_D(NR_MAC,"resp_refcount[%d] %d\n",sched_response_id,resp_refcount[sched_response_id]);
|
||||
resp_refcount[sched_response_id]--;
|
||||
if (resp_refcount[sched_response_id] == 0)
|
||||
release_sched_response(sched_response_id);
|
||||
@@ -141,6 +143,8 @@ void inc_ref_sched_response(int sched_response_id)
|
||||
if (sched_response_id == -1)
|
||||
return;
|
||||
|
||||
LOG_D(NR_MAC,"Incrementing sched_resp resp_refounct[%d] = %d\n",
|
||||
sched_response_id,resp_refcount[sched_response_id]);
|
||||
if (pthread_mutex_lock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_lock failed\n");
|
||||
|
||||
|
||||
@@ -734,7 +734,7 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request,
|
||||
fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot);
|
||||
fill_dci_from_dl_config(&mac->dl_info, dl_config);
|
||||
}
|
||||
nr_ue_dl_scheduler(&mac->dl_info);
|
||||
nr_ue_dl_scheduler(mac, &mac->dl_info);
|
||||
nr_ue_dl_indication(&mac->dl_info);
|
||||
|
||||
if (pthread_mutex_unlock(&mac->mutex_dl_info))
|
||||
@@ -749,7 +749,7 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request,
|
||||
// If we filled dl_info AFTER we got the slot indication, we want to check if we should fill tx_req:
|
||||
nr_uplink_indication_t ul_info = {.slot = (slot + slot_ahead) % slots_per_frame,
|
||||
.frame = slot + slot_ahead >= slots_per_frame ? (frame + 1) % 1024 : frame};
|
||||
nr_ue_ul_scheduler(&ul_info);
|
||||
nr_ue_ul_scheduler(mac, &ul_info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1030,7 +1030,7 @@ void *nrue_standalone_pnf_task(void *context)
|
||||
}
|
||||
|
||||
// L2 Abstraction Layer
|
||||
static int handle_bcch_bch(module_id_t module_id,
|
||||
static int handle_bcch_bch(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
void *phy_data,
|
||||
@@ -1041,7 +1041,6 @@ static int handle_bcch_bch(module_id_t module_id,
|
||||
uint16_t ssb_start_subcarrier,
|
||||
uint16_t cell_id)
|
||||
{
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
mac->mib_ssb = ssb_index;
|
||||
mac->physCellId = cell_id;
|
||||
mac->mib_additional_bits = additional_bits;
|
||||
@@ -1049,30 +1048,30 @@ static int handle_bcch_bch(module_id_t module_id,
|
||||
mac->frequency_range = FR2;
|
||||
else
|
||||
mac->frequency_range = FR1;
|
||||
nr_mac_rrc_data_ind_ue(module_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_BCH, (uint8_t *) pduP, 3); // fixed 3 bytes MIB PDU
|
||||
nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, NR_BCCH_BCH, (uint8_t *) pduP, 3); // fixed 3 bytes MIB PDU
|
||||
return 0;
|
||||
}
|
||||
|
||||
// L2 Abstraction Layer
|
||||
static int handle_bcch_dlsch(module_id_t module_id,
|
||||
static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
uint8_t ack_nack,
|
||||
uint8_t *pduP,
|
||||
uint32_t pdu_len)
|
||||
{
|
||||
return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, ack_nack, pduP, pdu_len);
|
||||
return nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len);
|
||||
}
|
||||
|
||||
// L2 Abstraction Layer
|
||||
static int handle_dci(module_id_t module_id,
|
||||
static int handle_dci(NR_UE_MAC_INST_t *mac,
|
||||
int cc_id,
|
||||
unsigned int gNB_index,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
fapi_nr_dci_indication_pdu_t *dci)
|
||||
{
|
||||
return nr_ue_process_dci_indication_pdu(module_id, cc_id, gNB_index, frame, slot, dci);
|
||||
return nr_ue_process_dci_indication_pdu(mac, cc_id, gNB_index, frame, slot, dci);
|
||||
}
|
||||
|
||||
static void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm)
|
||||
@@ -1096,26 +1095,26 @@ static int8_t handle_dlsch(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid,
|
||||
dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack);
|
||||
if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack)
|
||||
nr_ue_send_sdu(dl_info, pdu_id);
|
||||
nr_ue_send_sdu(mac, dl_info, pdu_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_rlm(rlm_t rlm_result, int frame, module_id_t module_id)
|
||||
static void handle_rlm(rlm_t rlm_result, int frame, NR_UE_MAC_INST_t *mac)
|
||||
{
|
||||
if (rlm_result == RLM_no_monitoring)
|
||||
return;
|
||||
bool is_sync = rlm_result == RLM_in_sync ? true : false;
|
||||
nr_mac_rrc_sync_ind(module_id, frame, is_sync);
|
||||
nr_mac_rrc_sync_ind(mac->ue_id, frame, is_sync);
|
||||
}
|
||||
|
||||
static int8_t handle_csirs_measurements(module_id_t module_id,
|
||||
static int8_t handle_csirs_measurements(NR_UE_MAC_INST_t *mac,
|
||||
frame_t frame,
|
||||
int slot,
|
||||
fapi_nr_csirs_measurements_t *csirs_measurements)
|
||||
{
|
||||
handle_rlm(csirs_measurements->radiolink_monitoring, frame, module_id);
|
||||
return nr_ue_process_csirs_measurements(module_id, frame, slot, csirs_measurements);
|
||||
handle_rlm(csirs_measurements->radiolink_monitoring, frame, mac);
|
||||
return nr_ue_process_csirs_measurements(mac, frame, slot, csirs_measurements);
|
||||
}
|
||||
|
||||
void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack)
|
||||
@@ -1147,11 +1146,10 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info)
|
||||
module_id_t module_id = ul_info->module_id;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
|
||||
LOG_T(NR_MAC, "In %s():%d not calling scheduler mac->ra.ra_state = %d\n",
|
||||
__FUNCTION__, __LINE__, mac->ra.ra_state);
|
||||
LOG_T(NR_MAC, "Not calling scheduler mac->ra.ra_state = %d\n", mac->ra.ra_state);
|
||||
|
||||
if (mac->phy_config_request_sent && is_nr_UL_slot(mac->tdd_UL_DL_ConfigurationCommon, ul_info->slot, mac->frame_type))
|
||||
nr_ue_ul_scheduler(ul_info);
|
||||
nr_ue_ul_scheduler(mac, ul_info);
|
||||
pthread_mutex_unlock(&mac_IF_mutex);
|
||||
|
||||
return 0;
|
||||
@@ -1160,15 +1158,14 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info)
|
||||
static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info)
|
||||
{
|
||||
uint32_t ret_mask = 0x0;
|
||||
module_id_t module_id = dl_info->module_id;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(dl_info->module_id);
|
||||
|
||||
// DL indication after reception of DCI or DL PDU
|
||||
if (dl_info && dl_info->dci_ind && dl_info->dci_ind->number_of_dcis) {
|
||||
LOG_T(MAC, "[L2][IF MODULE][DL INDICATION][DCI_IND]\n");
|
||||
for (int i = 0; i < dl_info->dci_ind->number_of_dcis; i++) {
|
||||
LOG_T(MAC, ">>>NR_IF_Module i=%d, dl_info->dci_ind->number_of_dcis=%d\n", i, dl_info->dci_ind->number_of_dcis);
|
||||
int8_t ret = handle_dci(dl_info->module_id,
|
||||
int8_t ret = handle_dci(mac,
|
||||
dl_info->cc_id,
|
||||
dl_info->gNB_index,
|
||||
dl_info->frame,
|
||||
@@ -1188,14 +1185,14 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info)
|
||||
LOG_T(NR_MAC, "Setting harq_pid = %d and dci_index = %d (based on format)\n", g_harq_pid, dci_index->dci_format);
|
||||
|
||||
ret_mask |= (ret << FAPI_NR_DCI_IND);
|
||||
AssertFatal(nr_ue_if_module_inst[module_id] != NULL, "IF module is NULL!\n");
|
||||
AssertFatal(nr_ue_if_module_inst[dl_info->module_id] != NULL, "IF module is NULL!\n");
|
||||
fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, dl_info->slot);
|
||||
nr_scheduled_response_t scheduled_response = {.dl_config = dl_config,
|
||||
.mac = mac,
|
||||
.module_id = dl_info->module_id,
|
||||
.CC_id = dl_info->cc_id,
|
||||
.phy_data = dl_info->phy_data};
|
||||
nr_ue_if_module_inst[module_id]->scheduled_response(&scheduled_response);
|
||||
nr_ue_if_module_inst[dl_info->module_id]->scheduled_response(&scheduled_response);
|
||||
memset(def_dci_pdu_rel15, 0, sizeof(*def_dci_pdu_rel15));
|
||||
}
|
||||
dl_info->dci_ind = NULL;
|
||||
@@ -1216,12 +1213,15 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info)
|
||||
case FAPI_NR_RX_PDU_TYPE_SSB:
|
||||
handle_rlm(rx_indication_body.ssb_pdu.radiolink_monitoring,
|
||||
dl_info->frame,
|
||||
dl_info->module_id);
|
||||
mac);
|
||||
if(rx_indication_body.ssb_pdu.decoded_pdu) {
|
||||
handle_ssb_meas(mac,
|
||||
rx_indication_body.ssb_pdu.ssb_index,
|
||||
rx_indication_body.ssb_pdu.rsrp_dBm);
|
||||
ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, dl_info->phy_data,
|
||||
ret_mask |= (handle_bcch_bch(mac,
|
||||
dl_info->cc_id,
|
||||
dl_info->gNB_index,
|
||||
dl_info->phy_data,
|
||||
rx_indication_body.ssb_pdu.pdu,
|
||||
rx_indication_body.ssb_pdu.additional_bits,
|
||||
rx_indication_body.ssb_pdu.ssb_index,
|
||||
@@ -1231,7 +1231,7 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info)
|
||||
}
|
||||
break;
|
||||
case FAPI_NR_RX_PDU_TYPE_SIB:
|
||||
ret_mask |= (handle_bcch_dlsch(dl_info->module_id,
|
||||
ret_mask |= (handle_bcch_dlsch(mac,
|
||||
dl_info->cc_id, dl_info->gNB_index,
|
||||
rx_indication_body.pdsch_pdu.ack_nack,
|
||||
rx_indication_body.pdsch_pdu.pdu,
|
||||
@@ -1248,7 +1248,7 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info)
|
||||
LOG_I(PHY, "RAR-Msg2 decoded\n");
|
||||
break;
|
||||
case FAPI_NR_CSIRS_IND:
|
||||
ret_mask |= (handle_csirs_measurements(dl_info->module_id,
|
||||
ret_mask |= (handle_csirs_measurements(mac,
|
||||
dl_info->frame,
|
||||
dl_info->slot,
|
||||
&rx_indication_body.csirs_measurements)) << FAPI_NR_CSIRS_IND;
|
||||
@@ -1267,9 +1267,10 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info)
|
||||
int ret = pthread_mutex_lock(&mac_IF_mutex);
|
||||
AssertFatal(!ret, "mutex failed %d\n", ret);
|
||||
uint32_t ret2 = 0;
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(dl_info->module_id);
|
||||
if (!dl_info->dci_ind && !dl_info->rx_ind)
|
||||
// DL indication to process DCI reception
|
||||
nr_ue_dl_scheduler(dl_info);
|
||||
nr_ue_dl_scheduler(mac, dl_info);
|
||||
else
|
||||
// DL indication to process data channels
|
||||
ret2 = nr_ue_dl_processing(dl_info);
|
||||
|
||||
@@ -102,6 +102,10 @@
|
||||
#include "BIT_STRING.h"
|
||||
#include "assertions.h"
|
||||
|
||||
#ifdef E2_AGENT
|
||||
#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h"
|
||||
#endif
|
||||
|
||||
//#define XER_PRINT
|
||||
|
||||
extern RAN_CONTEXT_t RC;
|
||||
@@ -500,6 +504,10 @@ static void rrc_gNB_process_RRCSetupComplete(const protocol_ctxt_t *const ctxt_p
|
||||
AssertFatal(ctxt_pP->rntiMaybeUEid == ue_context_pP->ue_context.rrc_ue_id, "logic bug: inconsistent IDs, must use CU UE ID!\n");
|
||||
|
||||
rrc_gNB_send_NGAP_NAS_FIRST_REQ(ctxt_pP, ue_context_pP, rrcSetupComplete);
|
||||
|
||||
#ifdef E2_AGENT
|
||||
signal_rrc_state_changed_to(&ue_context_pP->ue_context, RC_SM_RRC_CONNECTED);
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -2585,6 +2593,10 @@ rrc_gNB_generate_RRCRelease(
|
||||
rrc->cucp_cuup.bearer_context_release(assoc_id, &cmd);
|
||||
}
|
||||
|
||||
#ifdef E2_AGENT
|
||||
signal_rrc_state_changed_to(UE, RC_SM_RRC_IDLE);
|
||||
#endif
|
||||
|
||||
/* UE will be freed after UE context release complete */
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,32 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
|
||||
AssertFatal(false, "use RLC instead\n");
|
||||
break;
|
||||
|
||||
case NR_SBCCH_SL_BCH:
|
||||
if (pdu_len>0) {
|
||||
LOG_T(NR_RRC, "[UE %d] Received SL-MIB for NR_SBCCH_SL_BCH.\n", module_id);
|
||||
|
||||
MessageDef *message_p;
|
||||
int msg_sdu_size = BCCH_SDU_SIZE;
|
||||
|
||||
if (pdu_len > msg_sdu_size) {
|
||||
LOG_E(NR_RRC, "SDU larger than NR_SBCCH_SL_BCH SDU buffer size (%d, %d)", sdu_size, msg_sdu_size);
|
||||
sdu_size = msg_sdu_size;
|
||||
} else {
|
||||
sdu_size = pdu_len;
|
||||
}
|
||||
|
||||
message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_SBCCH_DATA_IND);
|
||||
memset(NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu, 0, BCCH_SDU_SIZE);
|
||||
memcpy(NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu, pduP, sdu_size);
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).frame = frame; //frameP
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).slot = slot;
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).sdu_size = sdu_size;
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).gnb_index = gNB_index;
|
||||
NR_RRC_MAC_SBCCH_DATA_IND (message_p).rx_slss_id = rnti;//rx_slss_id is rnti
|
||||
itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(module_id), message_p);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -324,10 +324,8 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst)
|
||||
// SRB0 activated by default
|
||||
ptr->Srb[0] = RB_ESTABLISHED;
|
||||
}
|
||||
}
|
||||
|
||||
if (get_softmodem_params()->sl_mode) {
|
||||
configure_NR_SL_Preconfig(get_softmodem_params()->sync_ref);
|
||||
init_sidelink(rrc);
|
||||
}
|
||||
|
||||
return NR_UE_rrc_inst;
|
||||
@@ -1437,6 +1435,14 @@ void *rrc_nrue(void *notUsed)
|
||||
nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(rrc, bcch->gnb_index, bcch->sdu, bcch->sdu_size, bcch->rsrq, bcch->rsrp);
|
||||
break;
|
||||
|
||||
case NR_RRC_MAC_SBCCH_DATA_IND:
|
||||
LOG_D(NR_RRC, "[UE %ld] Received %s: gNB %d\n", instance, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_SBCCH_DATA_IND(msg_p).gnb_index);
|
||||
NRRrcMacSBcchDataInd *sbcch = &NR_RRC_MAC_SBCCH_DATA_IND(msg_p);
|
||||
|
||||
nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(rrc, sbcch->gnb_index,sbcch->frame, sbcch->slot, sbcch->sdu,
|
||||
sbcch->sdu_size, sbcch->rx_slss_id);
|
||||
break;
|
||||
|
||||
case NR_RRC_MAC_CCCH_DATA_IND: {
|
||||
NRRrcMacCcchDataInd *ind = &NR_RRC_MAC_CCCH_DATA_IND(msg_p);
|
||||
nr_rrc_ue_decode_ccch(rrc, ind, 0);
|
||||
@@ -1921,3 +1927,17 @@ void handle_t300_expiry(NR_UE_RRC_INST_t *rrc)
|
||||
// TODO handle connEstFailureControl
|
||||
// TODO inform upper layers about the failure to establish the RRC connection
|
||||
}
|
||||
|
||||
//This calls the sidelink preconf message after RRC, MAC instances are created.
|
||||
void start_sidelink(int instance)
|
||||
{
|
||||
|
||||
NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[instance];
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
|
||||
//Process the Sidelink Preconfiguration
|
||||
rrc_ue_process_sidelink_Preconfiguration(rrc, get_softmodem_params()->sync_ref);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
#include "NR_DL-DCCH-Message.h"
|
||||
#include "NR_SystemInformation.h"
|
||||
#include "NR_UE-NR-Capability.h"
|
||||
#include "NR_SL-PreconfigurationNR-r16.h"
|
||||
#include "NR_MasterInformationBlockSidelink.h"
|
||||
|
||||
#include "RRC/NR/nr_rrc_common.h"
|
||||
#include "as_message.h"
|
||||
@@ -210,6 +212,10 @@ typedef struct NR_UE_RRC_INST_s {
|
||||
long selected_plmn_identity;
|
||||
Rrc_State_NR_t nrRrcState;
|
||||
as_nas_info_t initialNasMsg;
|
||||
|
||||
//Sidelink params
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfig;
|
||||
|
||||
} NR_UE_RRC_INST_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -121,7 +121,20 @@ void handle_rlf_sync(NR_UE_Timers_Constants_t *tac, nr_sync_msg_t sync_msg);
|
||||
void nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(NR_UE_RRC_INST_t *rrc,
|
||||
struct NR_SetupRelease_RLF_TimersAndConstants *rlf_TimersAndConstants);
|
||||
|
||||
int configure_NR_SL_Preconfig(int sync_source);
|
||||
int configure_NR_SL_Preconfig(NR_UE_RRC_INST_t *rrc,int sync_source);
|
||||
|
||||
void init_sidelink(NR_UE_RRC_INST_t *rrc);
|
||||
void start_sidelink(int instance);
|
||||
|
||||
void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst, int sync_ref);
|
||||
|
||||
void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
const uint8_t gNB_index,
|
||||
const frame_t frame,
|
||||
const int slot,
|
||||
uint8_t* pduP,
|
||||
const sdu_size_t pdu_len,
|
||||
const uint16_t rx_slss_id);
|
||||
|
||||
/** @}*/
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,17 @@
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "sl_preconfig_paramvalues.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "rrc_defs.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_proto.h"
|
||||
#include "nr-uesoftmodem.h"
|
||||
|
||||
void free_sl_rrc(NR_UE_RRC_INST_t *rrc)
|
||||
{
|
||||
|
||||
if (rrc->sl_preconfig) {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SL_PreconfigurationNR_r16, rrc->sl_preconfig);
|
||||
}
|
||||
}
|
||||
|
||||
static void prepare_NR_SL_SyncConfig(NR_SL_SyncConfig_r16_t *sl_syncconfig)
|
||||
{
|
||||
@@ -399,8 +410,7 @@ NR_SL_PreconfigurationNR_r16_t *prepare_NR_SL_PRECONFIGURATION(uint16_t num_tx_p
|
||||
return sl_preconfiguration;
|
||||
}
|
||||
|
||||
|
||||
int configure_NR_SL_Preconfig(int sync_source)
|
||||
int configure_NR_SL_Preconfig(NR_UE_RRC_INST_t *rrc,int sync_source)
|
||||
{
|
||||
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfig = NULL;
|
||||
@@ -424,9 +434,136 @@ int configure_NR_SL_Preconfig(int sync_source)
|
||||
}
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_SL_PreconfigurationNR_r16, sl_preconfig);
|
||||
sl_preconfig = NULL;
|
||||
//END.......
|
||||
rrc->sl_preconfig = sl_preconfig;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*decode SL-BCH (SL-MIB) message*/
|
||||
static int8_t nr_sl_rrc_ue_decode_SL_MIB(const uint8_t gNB_index,
|
||||
uint8_t *const bufferP,
|
||||
const uint8_t buffer_len)
|
||||
{
|
||||
NR_MasterInformationBlockSidelink_t *sl_mib = NULL;
|
||||
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_MasterInformationBlockSidelink,
|
||||
(void **)&sl_mib,
|
||||
(const void *)bufferP, buffer_len);
|
||||
|
||||
int ret = 0;
|
||||
if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) {
|
||||
LOG_E(NR_RRC, "SL-MIB decode error\n");
|
||||
ret = -1;
|
||||
} else {
|
||||
|
||||
int bits_unused = sl_mib->directFrameNumber_r16.bits_unused;
|
||||
uint16_t val_fn = sl_mib->directFrameNumber_r16.buf[0];
|
||||
val_fn = (val_fn << (8 - bits_unused)) + (sl_mib->directFrameNumber_r16.buf[1] >> bits_unused);
|
||||
|
||||
uint8_t val_slot = sl_mib->slotIndex_r16.buf[0];
|
||||
|
||||
LOG_D(NR_RRC, "SL-RRC - Received MIB\n");
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - DFN:%d\n" , val_fn);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - SLOT:%d\n" , val_slot >> 1);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - Incoverage:%d\n", sl_mib->inCoverage_r16);
|
||||
LOG_D(NR_RRC, "SL-MIB Contents - sl-TDD-Config:%x\n" , *((uint16_t *)(sl_mib->sl_TDD_Config_r16.buf)));
|
||||
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_MasterInformationBlockSidelink, sl_mib);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
|
||||
const uint8_t gNB_index,
|
||||
const frame_t frame,
|
||||
const int slot,
|
||||
uint8_t* pduP,
|
||||
const sdu_size_t pdu_len,
|
||||
const uint16_t rx_slss_id)
|
||||
{
|
||||
|
||||
nr_sl_rrc_ue_decode_SL_MIB(gNB_index, (uint8_t*)pduP, pdu_len);
|
||||
|
||||
DevAssert(rrc->sl_preconfig);
|
||||
|
||||
NR_SL_FreqConfigCommon_r16_t *fcfg = NULL;
|
||||
if (rrc->sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16)
|
||||
fcfg = rrc->sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0];
|
||||
DevAssert(fcfg);
|
||||
|
||||
NR_SL_SSB_TimeAllocation_r16_t *sl_SSB_TimeAllocation = NULL;
|
||||
|
||||
//Current implementation only supports one SSB Timeallocation
|
||||
//Extend RRC to use multiple SSB Time allocations TBD....
|
||||
if (fcfg->sl_SyncConfigList_r16)
|
||||
sl_SSB_TimeAllocation = fcfg->sl_SyncConfigList_r16->list.array[0]->sl_SSB_TimeAllocation1_r16;
|
||||
DevAssert(sl_SSB_TimeAllocation);
|
||||
|
||||
nr_rrc_mac_config_req_sl_mib(rrc->ue_id,
|
||||
sl_SSB_TimeAllocation,
|
||||
rx_slss_id,
|
||||
pduP);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst,
|
||||
sl_sync_source_enum_t sync_source)
|
||||
{
|
||||
|
||||
AssertFatal(rrc_inst, "RRC instance not created.\n");
|
||||
|
||||
NR_SL_PreconfigurationNR_r16_t *sl_preconfig = rrc_inst->sl_preconfig;
|
||||
AssertFatal(rrc_inst->sl_preconfig, "Check if SL-preconfig was created");
|
||||
|
||||
AssertFatal(sync_source != SL_SYNC_SOURCE_GNBENB, "Sync source GNB not supported\n");
|
||||
|
||||
nr_rrc_mac_config_req_sl_preconfig(rrc_inst->ue_id, sl_preconfig, sync_source);
|
||||
|
||||
//TBD.. These should be chosen by RRC according to 3GPP 38.331 RRC specification.
|
||||
//Currently hardcoding the values to these
|
||||
uint16_t slss_id = 671, ssb_ta_index = 1;
|
||||
//12 bits -sl-TDD-config will be filled by MAC
|
||||
//Incoverage 1bit is FALSE as this is mode 2
|
||||
//DFN, sfn will be filled by PHY
|
||||
uint8_t sl_mib_payload[4] = {0,0,0,0};
|
||||
|
||||
NR_SL_SSB_TimeAllocation_r16_t *ssb_ta = NULL;
|
||||
NR_SL_FreqConfigCommon_r16_t *fcfg = NULL;
|
||||
NR_SL_SyncConfig_r16_t *synccfg = NULL;
|
||||
if (sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16)
|
||||
fcfg = sl_preconfig->sidelinkPreconfigNR_r16.sl_PreconfigFreqInfoList_r16->list.array[0];
|
||||
AssertFatal(fcfg, "Fcfg cannot be NULL\n");
|
||||
if (fcfg->sl_SyncConfigList_r16)
|
||||
synccfg = fcfg->sl_SyncConfigList_r16->list.array[0];
|
||||
AssertFatal(synccfg, "Synccfg cannot be NULL\n");
|
||||
|
||||
if (ssb_ta_index == 1)
|
||||
ssb_ta = synccfg->sl_SSB_TimeAllocation1_r16;
|
||||
else if (ssb_ta_index == 2)
|
||||
ssb_ta = synccfg->sl_SSB_TimeAllocation2_r16;
|
||||
else if (ssb_ta_index == 3)
|
||||
ssb_ta = synccfg->sl_SSB_TimeAllocation3_r16;
|
||||
else DevAssert(0);
|
||||
|
||||
AssertFatal(ssb_ta, "SSB_timeallocation cannot be NULL\n");
|
||||
|
||||
if (sync_source == SL_SYNC_SOURCE_LOCAL_TIMING || sync_source == SL_SYNC_SOURCE_GNSS)
|
||||
nr_rrc_mac_transmit_slss_req(rrc_inst->ue_id,sl_mib_payload, slss_id, ssb_ta);
|
||||
|
||||
}
|
||||
|
||||
//For Sidelink mode 2 operation this prepares the sidelink preconfiguration
|
||||
void init_sidelink(NR_UE_RRC_INST_t *rrc)
|
||||
{
|
||||
int sync_ref = get_softmodem_params()->sync_ref;
|
||||
|
||||
if (get_softmodem_params()->sl_mode == 2) {
|
||||
//Preparation of the Sidelink PRE-Configuration message
|
||||
configure_NR_SL_Preconfig(rrc, sync_ref);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ void *trx_eth_write_udp_cmd(udpTXelem_t *udpTXelem) {
|
||||
TS -= device->txrx_offset;
|
||||
int TSinc = (6*256*device->sampling_rate_ratio_d)/device->sampling_rate_ratio_n;
|
||||
int len=256;
|
||||
LOG_D(PHY,"TS %llu (%llu),txrx_offset %d,d %d, n %d, buff[0] %p buff[1] %p\n",
|
||||
LOG_D(NR_PHY,"in eth send: TS %llu (%llu),txrx_offset %d,d %d, n %d, buff[0] %p buff[1] %p\n",
|
||||
(unsigned long long)TS,(unsigned long long)timestamp,device->txrx_offset,device->sampling_rate_ratio_d,device->sampling_rate_ratio_n,
|
||||
buff[0],buff[1]);
|
||||
for (int offset=0;offset<nsamps;offset+=256,TS+=TSinc) {
|
||||
@@ -349,7 +349,7 @@ void *trx_eth_write_udp_cmd(udpTXelem_t *udpTXelem) {
|
||||
*(uint8_t *)(buff2 + 2) = len>>8;
|
||||
*(uint8_t *)(buff2 + 3) = len&0xff;
|
||||
for (int aid = 0; aid<nant; aid++) {
|
||||
LOG_D(PHY,"TS %llu (TS0 %llu) aa %d : offset %d, len %d\n",(unsigned long long)TS,(unsigned long long)fhstate->TS0,aid,offset,len);
|
||||
LOG_D(NR_PHY,"TS %llu (TS0 %llu) aa %d : offset %d, len %d\n",(unsigned long long)TS,(unsigned long long)fhstate->TS0,aid,offset,len);
|
||||
// ECPRI PC_ID (2 bytes)
|
||||
*(uint16_t *)(buff2 + 4) = aid;
|
||||
// bring TX data into 12 MSBs
|
||||
@@ -383,6 +383,7 @@ void *trx_eth_write_udp_cmd(udpTXelem_t *udpTXelem) {
|
||||
} // aid
|
||||
} // offset
|
||||
free(buff);
|
||||
LOG_D(NR_PHY,"Returning from eth send\n");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
pkg_check_modules(dpdk REQUIRED libdpdk)
|
||||
pkg_check_modules(numa REQUIRED numa)
|
||||
|
||||
find_package(xran 5.1.1 EXACT REQUIRED) # E release -> 5
|
||||
find_package(xran 5.1.2 EXACT REQUIRED) # E release -> 5
|
||||
|
||||
# Ignore xran-specific warning: we don't care/can't change the following warning, so suppress
|
||||
# alignment 1 of 'struct XYZ' is less than 2
|
||||
|
||||
+71
-70
@@ -81,7 +81,11 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
|
||||
struct xran_device_ctx *xran_ctx = xran_dev_get_ctx();
|
||||
const struct xran_fh_init *fh_init = &xran_ctx->fh_init;
|
||||
int num_ports = fh_init->xran_ports;
|
||||
static int rx_RU[XRAN_PORTS_NUM][20] = {0};
|
||||
|
||||
const struct xran_fh_config *fh_config = &xran_ctx->fh_cfg;
|
||||
const int slots_per_subframe = 1 << fh_config->frame_conf.nNumerology;
|
||||
|
||||
static int rx_RU[XRAN_PORTS_NUM][160] = {0};
|
||||
uint32_t rx_tti = callback_tag->slotiId;
|
||||
|
||||
tti = xran_get_slot_idx_from_tti(rx_tti, &frame, &subframe, &slot, &second);
|
||||
@@ -95,7 +99,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status)
|
||||
}
|
||||
first_rx_set = 1;
|
||||
if (first_read_set == 1) {
|
||||
slot2 = slot + (subframe << 1);
|
||||
slot2 = slot + (subframe * slots_per_subframe);
|
||||
rx_RU[ru_id][slot2] = 1;
|
||||
if (last_frame > 0 && frame > 0
|
||||
&& ((slot2 > 0 && last_frame != frame) || (slot2 == 0 && last_frame != ((1024 + frame - 1) & 1023))))
|
||||
@@ -164,14 +168,17 @@ int oai_physide_ul_full_slot_call_back(void *param)
|
||||
int read_prach_data(ru_info_t *ru, int frame, int slot)
|
||||
{
|
||||
/* calculate tti and subframe_id from frame, slot num */
|
||||
int tti = 20 * (frame) + (slot);
|
||||
uint32_t subframe = XranGetSubFrameNum(tti, 2, 10);
|
||||
uint32_t is_prach_slot = xran_is_prach_slot(0, subframe, (slot % 2));
|
||||
int sym_idx = 0;
|
||||
|
||||
struct xran_device_ctx *xran_ctx = xran_dev_get_ctx();
|
||||
struct xran_prach_cp_config *pPrachCPConfig = &(xran_ctx->PrachCPConfig);
|
||||
struct xran_ru_config *ru_conf = &(xran_ctx->fh_cfg.ru_conf);
|
||||
int slots_per_frame = 10 << xran_ctx->fh_cfg.frame_conf.nNumerology;
|
||||
int slots_per_subframe = 1 << xran_ctx->fh_cfg.frame_conf.nNumerology;
|
||||
|
||||
int tti = slots_per_frame * (frame) + (slot);
|
||||
uint32_t subframe = slot / slots_per_subframe;
|
||||
uint32_t is_prach_slot = xran_is_prach_slot(0, subframe, (slot % slots_per_subframe));
|
||||
|
||||
int nb_rx_per_ru = ru->nb_rx / xran_ctx->fh_init.xran_ports;
|
||||
/* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */
|
||||
@@ -275,17 +282,19 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
#endif
|
||||
// return(0);
|
||||
|
||||
int tti = (*frame * 20) + *slot;
|
||||
struct xran_device_ctx *xran_ctx = xran_dev_get_ctx();
|
||||
int slots_per_frame = 10 << xran_ctx->fh_cfg.frame_conf.nNumerology;
|
||||
|
||||
int tti = slots_per_frame * (*frame) + (*slot);
|
||||
|
||||
read_prach_data(ru, *frame, *slot);
|
||||
|
||||
struct xran_device_ctx *xran_ctx = xran_dev_get_ctx();
|
||||
const struct xran_fh_init *fh_init = &xran_ctx->fh_init;
|
||||
int nPRBs = xran_ctx->fh_cfg.nULRBs;
|
||||
int fftsize = 1 << xran_ctx->fh_cfg.ru_conf.fftSize;
|
||||
|
||||
int slot_offset_rxdata = 3 & (*slot);
|
||||
uint32_t slot_size = 4 * 14 * 4096;
|
||||
uint32_t slot_size = 4 * 14 * fftsize;
|
||||
uint8_t *rx_data = (uint8_t *)ru->rxdataF[0];
|
||||
uint8_t *start_ptr = NULL;
|
||||
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
|
||||
@@ -324,77 +333,71 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
else
|
||||
pData = p_sec_desc->pData;
|
||||
ptr = pData;
|
||||
pos = (int32_t *)(start_ptr + (4 * sym_idx * 4096));
|
||||
pos = (int32_t *)(start_ptr + (4 * sym_idx * fftsize));
|
||||
if (ptr == NULL || pos == NULL)
|
||||
continue;
|
||||
|
||||
uint8_t *u8dptr;
|
||||
struct xran_prb_map *pRbMap = pPrbMap;
|
||||
AssertFatal(ptr != NULL, "ptr NULL\n");
|
||||
AssertFatal(pos != NULL, "pos NULL\n");
|
||||
if (1) {
|
||||
uint32_t idxElm = 0;
|
||||
u8dptr = (uint8_t *)ptr;
|
||||
int16_t payload_len = 0;
|
||||
|
||||
uint8_t *src = (uint8_t *)u8dptr;
|
||||
uint32_t idxElm = 0;
|
||||
uint8_t *src = (uint8_t *)ptr;
|
||||
int16_t payload_len = 0;
|
||||
|
||||
LOG_D(PHY, "pRbMap->nPrbElm %d\n", pRbMap->nPrbElm);
|
||||
for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
|
||||
LOG_D(PHY,
|
||||
"prbMap[%d] : PRBstart %d nPRBs %d\n",
|
||||
idxElm,
|
||||
pRbMap->prbMap[idxElm].nRBStart,
|
||||
pRbMap->prbMap[idxElm].nRBSize);
|
||||
pRbElm = &pRbMap->prbMap[idxElm];
|
||||
int pos_len = 0;
|
||||
int neg_len = 0;
|
||||
|
||||
if (pRbElm->nRBStart < (nPRBs >> 1)) // there are PRBs left of DC
|
||||
neg_len = min((nPRBs * 6) - (pRbElm->nRBStart * 12), pRbElm->nRBSize * N_SC_PER_PRB);
|
||||
pos_len = (pRbElm->nRBSize * N_SC_PER_PRB) - neg_len;
|
||||
LOG_D(PHY, "pRbMap->nPrbElm %d\n", pRbMap->nPrbElm);
|
||||
for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
|
||||
LOG_D(PHY,
|
||||
"prbMap[%d] : PRBstart %d nPRBs %d\n",
|
||||
idxElm,
|
||||
pRbMap->prbMap[idxElm].nRBStart,
|
||||
pRbMap->prbMap[idxElm].nRBSize);
|
||||
pRbElm = &pRbMap->prbMap[idxElm];
|
||||
int pos_len = 0;
|
||||
int neg_len = 0;
|
||||
|
||||
src = pData;
|
||||
// Calculation of the pointer for the section in the buffer.
|
||||
// positive half
|
||||
uint8_t *dst1 = (uint8_t *)(pos + (neg_len == 0 ? ((pRbElm->nRBStart * N_SC_PER_PRB) - (nPRBs * 6)) : 0));
|
||||
// negative half
|
||||
uint8_t *dst2 = (uint8_t *)(pos + (pRbElm->nRBStart * N_SC_PER_PRB) + fftsize - (nPRBs * 6));
|
||||
int32_t local_dst[pRbElm->nRBSize * N_SC_PER_PRB] __attribute__((aligned(64)));
|
||||
if (pRbElm->compMethod == XRAN_COMPMETHOD_NONE) {
|
||||
// NOTE: gcc 11 knows how to generate AVX2 for this!
|
||||
for (idx = 0; idx < pRbElm->nRBSize * N_SC_PER_PRB * 2; idx++)
|
||||
((int16_t *)local_dst)[idx] = ((int16_t)ntohs(((uint16_t *)src)[idx])) >> 2;
|
||||
memcpy((void *)dst2, (void *)local_dst, neg_len * 4);
|
||||
memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4);
|
||||
} else if (pRbElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) {
|
||||
struct xranlib_decompress_request bfp_decom_req;
|
||||
struct xranlib_decompress_response bfp_decom_rsp;
|
||||
if (pRbElm->nRBStart < (nPRBs >> 1)) // there are PRBs left of DC
|
||||
neg_len = min((nPRBs * 6) - (pRbElm->nRBStart * 12), pRbElm->nRBSize * N_SC_PER_PRB);
|
||||
pos_len = (pRbElm->nRBSize * N_SC_PER_PRB) - neg_len;
|
||||
|
||||
payload_len = (3 * pRbElm->iqWidth + 1) * pRbElm->nRBSize;
|
||||
src = pData;
|
||||
// Calculation of the pointer for the section in the buffer.
|
||||
// positive half
|
||||
uint8_t *dst1 = (uint8_t *)(pos + (neg_len == 0 ? ((pRbElm->nRBStart * N_SC_PER_PRB) - (nPRBs * 6)) : 0));
|
||||
// negative half
|
||||
uint8_t *dst2 = (uint8_t *)(pos + (pRbElm->nRBStart * N_SC_PER_PRB) + fftsize - (nPRBs * 6));
|
||||
int32_t local_dst[pRbElm->nRBSize * N_SC_PER_PRB] __attribute__((aligned(64)));
|
||||
if (pRbElm->compMethod == XRAN_COMPMETHOD_NONE) {
|
||||
// NOTE: gcc 11 knows how to generate AVX2 for this!
|
||||
for (idx = 0; idx < pRbElm->nRBSize * N_SC_PER_PRB * 2; idx++)
|
||||
((int16_t *)local_dst)[idx] = ((int16_t)ntohs(((uint16_t *)src)[idx])) >> 2;
|
||||
memcpy((void *)dst2, (void *)local_dst, neg_len * 4);
|
||||
memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4);
|
||||
} else if (pRbElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) {
|
||||
struct xranlib_decompress_request bfp_decom_req;
|
||||
struct xranlib_decompress_response bfp_decom_rsp;
|
||||
|
||||
memset(&bfp_decom_req, 0, sizeof(struct xranlib_decompress_request));
|
||||
memset(&bfp_decom_rsp, 0, sizeof(struct xranlib_decompress_response));
|
||||
payload_len = (3 * pRbElm->iqWidth + 1) * pRbElm->nRBSize;
|
||||
|
||||
bfp_decom_req.data_in = (int8_t *)src;
|
||||
bfp_decom_req.numRBs = pRbElm->nRBSize;
|
||||
bfp_decom_req.len = payload_len;
|
||||
bfp_decom_req.compMethod = pRbElm->compMethod;
|
||||
bfp_decom_req.iqWidth = pRbElm->iqWidth;
|
||||
memset(&bfp_decom_req, 0, sizeof(struct xranlib_decompress_request));
|
||||
memset(&bfp_decom_rsp, 0, sizeof(struct xranlib_decompress_response));
|
||||
|
||||
bfp_decom_rsp.data_out = (int16_t *)local_dst;
|
||||
bfp_decom_rsp.len = 0;
|
||||
bfp_decom_req.data_in = (int8_t *)src;
|
||||
bfp_decom_req.numRBs = pRbElm->nRBSize;
|
||||
bfp_decom_req.len = payload_len;
|
||||
bfp_decom_req.compMethod = pRbElm->compMethod;
|
||||
bfp_decom_req.iqWidth = pRbElm->iqWidth;
|
||||
|
||||
xranlib_decompress_avx512(&bfp_decom_req, &bfp_decom_rsp);
|
||||
memcpy((void *)dst2, (void *)local_dst, neg_len * 4);
|
||||
memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4);
|
||||
outcnt++;
|
||||
} else {
|
||||
printf("pRbElm->compMethod == %d is not supported\n", pRbElm->compMethod);
|
||||
exit(-1);
|
||||
}
|
||||
bfp_decom_rsp.data_out = (int16_t *)local_dst;
|
||||
bfp_decom_rsp.len = 0;
|
||||
|
||||
xranlib_decompress_avx512(&bfp_decom_req, &bfp_decom_rsp);
|
||||
memcpy((void *)dst2, (void *)local_dst, neg_len * 4);
|
||||
memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4);
|
||||
outcnt++;
|
||||
} else {
|
||||
printf("pRbElm->compMethod == %d is not supported\n", pRbElm->compMethod);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} // sym_ind
|
||||
} // ant_ind
|
||||
@@ -457,9 +460,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
.sBufferList.pBuffers->pData;
|
||||
struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData;
|
||||
ptr = pData;
|
||||
pos =
|
||||
&ru->txdataF_BF[ant_id][sym_idx * 4096 /*fp->ofdm_symbol_size*/]; // We had to use a different ru structure than benetel
|
||||
// so the access to the buffer is not the same.
|
||||
pos = &ru->txdataF_BF[ant_id][sym_idx * fftsize];
|
||||
|
||||
uint8_t *u8dptr;
|
||||
struct xran_prb_map *pRbMap = pPrbMap;
|
||||
|
||||
@@ -500,7 +500,7 @@ static bool set_fh_io_cfg(struct xran_io_cfg *io_cfg, const paramdef_t *fhip, in
|
||||
io_cfg->dpdkIoVaMode = 0; /* IOVA mode */
|
||||
io_cfg->dpdkMemorySize = 0; /* DPDK memory size */
|
||||
io_cfg->core = *gpd(fhip, nump, ORAN_CONFIG_IO_CORE)->iptr;
|
||||
io_cfg->system_core = 0; /* TODO how called in sample app? */
|
||||
io_cfg->system_core = *gpd(fhip, nump, ORAN_CONFIG_SYSTEM_CORE)->iptr;
|
||||
io_cfg->pkt_proc_core = get_u64_mask(gpd(fhip, nump, ORAN_CONFIG_WORKER_CORES));
|
||||
io_cfg->pkt_proc_core_64_127 = 0x0; // bitmap 0 -> no core
|
||||
io_cfg->pkt_aux_core = 0; /* sapmle app says 0 = "do not start" */
|
||||
@@ -684,9 +684,6 @@ static bool set_fh_prach_config(const openair0_config_t *oai0,
|
||||
{
|
||||
const split7_config_t *s7cfg = &oai0->split7;
|
||||
|
||||
// for FR2, need at least to update nPrachFilterIdx
|
||||
AssertFatal(oai0->nr_band < 100, "can only handle FR1!\n");
|
||||
|
||||
prach_config->nPrachConfIdx = s7cfg->prach_index;
|
||||
prach_config->nPrachSubcSpacing = oai0->nr_scs_for_raster;
|
||||
prach_config->nPrachZeroCorrConf = 0;
|
||||
@@ -694,7 +691,10 @@ static bool set_fh_prach_config(const openair0_config_t *oai0,
|
||||
prach_config->nPrachRootSeqIdx = 0;
|
||||
prach_config->nPrachFreqStart = s7cfg->prach_freq_start;
|
||||
prach_config->nPrachFreqOffset = (s7cfg->prach_freq_start * 12 - oai0->num_rb_dl * 6) * 2;
|
||||
prach_config->nPrachFilterIdx = get_prach_filterindex_fr1(oai0->duplex_mode, s7cfg->prach_index);
|
||||
if (oai0->nr_band < 100)
|
||||
prach_config->nPrachFilterIdx = get_prach_filterindex_fr1(oai0->duplex_mode, s7cfg->prach_index);
|
||||
else
|
||||
prach_config->nPrachFilterIdx = XRAN_FILTERINDEX_PRACH_ABC;
|
||||
prach_config->startSymId = 0;
|
||||
prach_config->lastSymId = 0;
|
||||
prach_config->startPrbc = 0;
|
||||
|
||||
@@ -78,32 +78,6 @@ static uint32_t get_nFpgaToSW_FTH_RxBufferLen(int mu)
|
||||
}
|
||||
}
|
||||
|
||||
/* is this necessary?
|
||||
int32_t set_main_core(uint32_t main_core)
|
||||
{
|
||||
struct sched_param sched_param;
|
||||
cpu_set_t cpuset;
|
||||
int32_t result = 0;
|
||||
memset(&sched_param, 0, sizeof(struct sched_param));
|
||||
// set main thread affinity mask to CPU2
|
||||
sched_param.sched_priority = 99;
|
||||
CPU_ZERO(&cpuset);
|
||||
|
||||
printf("This system has %d processors configured and %d processors available.\n", get_nprocs_conf(), get_nprocs());
|
||||
|
||||
if (main_core < get_nprocs_conf())
|
||||
CPU_SET(main_core, &cpuset);
|
||||
else
|
||||
return -1;
|
||||
|
||||
if ((result = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset))) {
|
||||
printf("pthread_setaffinity_np failed: coreId = 2, result = %d\n", result);
|
||||
}
|
||||
printf("%s [CPU %2d] [PID: %6d]\n", __FUNCTION__, sched_getcpu(), getpid());
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
static struct xran_prb_map get_xran_prb_map_dl(const struct xran_fh_config *f)
|
||||
{
|
||||
struct xran_prb_map prbmap = {
|
||||
@@ -432,11 +406,6 @@ int *oai_oran_initialize(const openair0_config_t *openair0_cfg)
|
||||
print_fh_config(&xran_fh_config[o_xu_id]);
|
||||
}
|
||||
|
||||
// if ((xret = set_main_core(init.something)) < 0) {
|
||||
// printf("set_main_core() failed %d\n", xret);
|
||||
// exit(-1);
|
||||
// }
|
||||
|
||||
xret = xran_init(0, NULL, &init, NULL, &gxran_handle);
|
||||
if (xret != XRAN_STATUS_SUCCESS) {
|
||||
printf("xran_init failed %d\n", xret);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define CONFIG_STRING_ORAN "fhi_72"
|
||||
|
||||
#define ORAN_CONFIG_DPDK_DEVICES "dpdk_devices"
|
||||
#define ORAN_CONFIG_SYSTEM_CORE "system_core"
|
||||
#define ORAN_CONFIG_IO_CORE "io_core"
|
||||
#define ORAN_CONFIG_WORKER_CORES "worker_cores"
|
||||
#define ORAN_CONFIG_DU_ADDR "du_addr"
|
||||
@@ -42,6 +43,7 @@
|
||||
// TODO: ethernet addr check
|
||||
#define ORAN_GLOBALPARAMS_DESC { \
|
||||
{ORAN_CONFIG_DPDK_DEVICES, "PCI addr of devices for DPDK\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
{ORAN_CONFIG_SYSTEM_CORE, "DPDK control threads core\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||
{ORAN_CONFIG_IO_CORE, "DPDK Core used for IO\n", PARAMFLAG_MANDATORY, .iptr=NULL, .defintval=4, TYPE_INT, 0}, \
|
||||
{ORAN_CONFIG_WORKER_CORES, "CPU Cores to use for workers\n", PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=NULL,TYPE_UINTARRAY, 0}, \
|
||||
{ORAN_CONFIG_DU_ADDR, "Ether addr of DU\n", PARAMFLAG_MANDATORY, .strlistptr=NULL, .defstrlistval=NULL, TYPE_STRINGLIST, 0}, \
|
||||
|
||||
@@ -209,10 +209,11 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
|
||||
printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX function \n", f, sl);
|
||||
}
|
||||
|
||||
int slots_per_frame = 10 << (ru->openair0_cfg.nr_scs_for_raster);
|
||||
proc->tti_rx = sl;
|
||||
proc->frame_rx = f;
|
||||
proc->tti_tx = (sl + sl_ahead) % 20;
|
||||
proc->frame_tx = (sl > (19 - sl_ahead)) ? (f + 1) & 1023 : f;
|
||||
proc->tti_tx = (sl + sl_ahead) % slots_per_frame;
|
||||
proc->frame_tx = (sl > (slots_per_frame - 1 - sl_ahead)) ? (f + 1) & 1023 : f;
|
||||
|
||||
if (proc->first_rx == 0) {
|
||||
if (proc->tti_rx != *slot) {
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
Active_gNBs = ( "gNB-OAI");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
sa = 1;
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
pdsch_AntennaPorts_XP = 1;
|
||||
pusch_AntennaPorts = 1;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
sib1_tda = 15;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# This is 27510.240 MHz + 16 * 12 * 120e3 MHz = 27533.280 MHz (GSCN: 22446)
|
||||
absoluteFrequencySSB = 2071387;
|
||||
dl_frequencyBand = 257;
|
||||
# This is 27510.240 MHz
|
||||
dl_absoluteFrequencyPointA = 2071003;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 3;
|
||||
dl_carrierBandwidth = 32;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# This is RBstart = 0, L = 32: (275 * (L - 1)) + RBstart
|
||||
initialDLBWPlocationAndBandwidth = 8525;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 3;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 0;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 257;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 3;
|
||||
ul_carrierBandwidth = 32;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 8525;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 3;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 59;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 12;
|
||||
preambleReceivedTargetPower = -96;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 5;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
msg1_SubcarrierSpacing = 3;
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -70;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 3;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 3;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 3;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 3;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ( { ipv4 = "192.168.70.132";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "demo-oai";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
#pusch_TargetSNRx10 = 150;
|
||||
#pucch_TargetSNRx10 = 200;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
#pucch0_dtx_threshold = 120;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes";
|
||||
nb_tx = 1;
|
||||
nb_rx = 1;
|
||||
att_tx = 0;
|
||||
att_rx = 0;
|
||||
sl_ahead = 12;
|
||||
bands = [257];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 60;
|
||||
eNB_instances = [0];
|
||||
#if_freq = 2650000000L;
|
||||
##beamforming 1x2 matrix: 1 layer x 2 antennas
|
||||
bf_weights = [0x00007fff, 0x0000];
|
||||
#clock_src = "internal";
|
||||
sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal"
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = 4043;
|
||||
options = (); #("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that an UE supports in chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
hw_log_level ="info";
|
||||
phy_log_level ="info";
|
||||
mac_log_level ="info";
|
||||
rlc_log_level ="info";
|
||||
pdcp_log_level ="info";
|
||||
rrc_log_level ="info";
|
||||
ngap_log_level ="info";
|
||||
f1ap_log_level ="info";
|
||||
};
|
||||
@@ -11,7 +11,7 @@ gNBs =
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
plmn_list = ({ mcc = 208; mnc = 98; mnc_length = 2; snssaiList = ({ sst = 1 }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
@@ -136,10 +136,10 @@ gNBs =
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
dl_UL_TransmissionPeriodicity = 5;
|
||||
nrofDownlinkSlots = 3;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSlots = 1;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
@@ -168,9 +168,9 @@ gNBs =
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai";
|
||||
GNB_INTERFACE_NAME_FOR_NG_AMF = "internet";
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "demo-oai";
|
||||
GNB_INTERFACE_NAME_FOR_NGU = "internet";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
@@ -186,6 +186,10 @@ MACRLCs = (
|
||||
pusch_TargetSNRx10 = 150;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
ulsch_max_frame_inactivity = 0;
|
||||
ul_max_mcs = 10;
|
||||
min_grant_prb = 20;
|
||||
min_grant_mcs = 16;
|
||||
dl_max_mcs = 10;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -204,8 +208,8 @@ RUs = (
|
||||
local_rf = "yes"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 6;
|
||||
att_rx = 6;
|
||||
att_tx = 0;
|
||||
att_rx = 0;
|
||||
bands = [41];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
@@ -213,6 +217,7 @@ RUs = (
|
||||
#beamforming 1x4 matrix:
|
||||
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||
clock_src = "internal";
|
||||
sl_ahead = 2;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ L1s = (
|
||||
#thread_pool_size = 8;
|
||||
tx_amp_backoff_dB = 3;
|
||||
L1_rx_thread_core = 8;
|
||||
L1_tx_thread_core = 10; # relevant after merge of l1_tx_thread
|
||||
L1_tx_thread_core = 10;
|
||||
phase_compensation = 0; # needs to match O-RU configuration
|
||||
}
|
||||
);
|
||||
@@ -284,6 +284,7 @@ log_config : {
|
||||
|
||||
fhi_72 = {
|
||||
dpdk_devices = ("0000:31:06.0", "0000:31:06.1");
|
||||
system_core = 0;
|
||||
io_core = 4;
|
||||
worker_cores = (2);
|
||||
du_addr = ("76:76:64:6e:00:01", "76:76:64:6e:00:01");
|
||||
|
||||
@@ -214,7 +214,7 @@ L1s = (
|
||||
max_ldpc_iterations = 10;
|
||||
tx_amp_backoff_dB = 20; # needs to match O-RU configuration
|
||||
L1_rx_thread_core = 8;
|
||||
L1_tx_thread_core = 10; # relevant after merge of l1_tx_thread
|
||||
L1_tx_thread_core = 10;
|
||||
phase_compensation = 0; # needs to match O-RU configuration
|
||||
}
|
||||
);
|
||||
@@ -272,6 +272,7 @@ log_config :
|
||||
|
||||
fhi_72 = {
|
||||
dpdk_devices = ("0000:31:06.0", "0000:31:06.1");
|
||||
system_core = 0;
|
||||
io_core = 4;
|
||||
worker_cores = (2);
|
||||
du_addr = ("00:11:22:33:44:66", "00:11:22:33:44:67");
|
||||
|
||||
@@ -215,7 +215,7 @@ L1s = (
|
||||
max_ldpc_iterations = 10;
|
||||
tx_amp_backoff_dB = 20; # needs to match O-RU configuration
|
||||
L1_rx_thread_core = 8;
|
||||
L1_tx_thread_core = 10; # relevant after merge of l1_tx_thread
|
||||
L1_tx_thread_core = 10;
|
||||
phase_compensation = 1; # needs to match O-RU configuration
|
||||
}
|
||||
);
|
||||
@@ -275,6 +275,7 @@ log_config :
|
||||
|
||||
fhi_72 = {
|
||||
dpdk_devices = ("0000:31:06.0", "0000:31:06.1");
|
||||
system_core = 0;
|
||||
io_core = 4;
|
||||
worker_cores = (2);
|
||||
du_addr = ("00:11:22:33:44:99", "00:11:22:33:44:99");
|
||||
|
||||
Reference in New Issue
Block a user