Merge remote-tracking branch 'origin/N2_HO_Measurement_config' into integration_2024_w22
This commit is contained in:
@@ -0,0 +1,321 @@
|
|||||||
|
Active_gNBs = ( "gNB-OAI");
|
||||||
|
# Asn1_verbosity, choice in: none, info, annoying
|
||||||
|
Asn1_verbosity = "none";
|
||||||
|
|
||||||
|
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; sd = 0x1; }) });
|
||||||
|
|
||||||
|
@include "neighbour-config.conf"
|
||||||
|
nr_cellid = 1;
|
||||||
|
|
||||||
|
////////// Physical parameters:
|
||||||
|
|
||||||
|
do_CSIRS = 0;
|
||||||
|
do_SRS = 0;
|
||||||
|
min_rxtxtime = 6;
|
||||||
|
pdcch_ConfigSIB1 = (
|
||||||
|
{
|
||||||
|
controlResourceSetZero = 12;
|
||||||
|
searchSpaceZero = 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
servingCellConfigCommon = (
|
||||||
|
{
|
||||||
|
#spCellConfigCommon
|
||||||
|
|
||||||
|
physCellId = 0;
|
||||||
|
|
||||||
|
# downlinkConfigCommon
|
||||||
|
#frequencyInfoDL
|
||||||
|
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
|
||||||
|
absoluteFrequencySSB = 641280;
|
||||||
|
dl_frequencyBand = 78;
|
||||||
|
# this is 3600 MHz
|
||||||
|
dl_absoluteFrequencyPointA = 640008;
|
||||||
|
#scs-SpecificCarrierList
|
||||||
|
dl_offstToCarrier = 0;
|
||||||
|
# subcarrierSpacing
|
||||||
|
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||||
|
dl_subcarrierSpacing = 1;
|
||||||
|
dl_carrierBandwidth = 106;
|
||||||
|
#initialDownlinkBWP
|
||||||
|
#genericParameters
|
||||||
|
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||||
|
initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952
|
||||||
|
# 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 = 106;
|
||||||
|
pMax = 20;
|
||||||
|
#initialUplinkBWP
|
||||||
|
#genericParameters
|
||||||
|
initialULBWPlocationAndBandwidth = 28875;
|
||||||
|
# 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 = -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 = 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 = 14;
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
# Dedicated Serving Cell Configuration
|
||||||
|
servingCellConfigDedicated = ({
|
||||||
|
# BWP-Downlink
|
||||||
|
# BWP 1 Configuration
|
||||||
|
dl_bwp-Id_1 = 1;
|
||||||
|
dl_bwp1_locationAndBandwidth = 28875; // RBstart=0, L=106 (40 MHz BW)
|
||||||
|
# subcarrierSpacing
|
||||||
|
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||||
|
dl_bwp1_subcarrierSpacing = 1;
|
||||||
|
|
||||||
|
# BWP 2 Configuration
|
||||||
|
dl_bwp-Id_2 = 2;
|
||||||
|
dl_bwp2_locationAndBandwidth = 13750; // RBstart=0, L=51 (20 MHz BW)
|
||||||
|
# subcarrierSpacing
|
||||||
|
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||||
|
dl_bwp2_subcarrierSpacing = 1;
|
||||||
|
|
||||||
|
# BWP 3 Configuration
|
||||||
|
dl_bwp-Id_3 = 3;
|
||||||
|
dl_bwp3_locationAndBandwidth = 6325; // RBstart=0, L=24 (10 MHz BW)
|
||||||
|
# subcarrierSpacing
|
||||||
|
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||||
|
dl_bwp3_subcarrierSpacing = 1;
|
||||||
|
|
||||||
|
firstActiveDownlinkBWP-Id = 1; #BWP-Id
|
||||||
|
defaultDownlinkBWP-Id = 1; #BWP-Id
|
||||||
|
|
||||||
|
# bwp-InactivityTimer ENUMERATED {ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30,
|
||||||
|
# ms40,ms50, ms60, ms80,ms100, ms200,ms300, ms500,
|
||||||
|
# ms750, ms1280, ms1920, ms2560, spare10, spare9, spare8,
|
||||||
|
# spare7, spare6, spare5, spare4, spare3, spare2, spare1 }
|
||||||
|
|
||||||
|
# UplinkConfig
|
||||||
|
# BWP-Uplink
|
||||||
|
# BWP 1 Configuration
|
||||||
|
ul_bwp-Id_1 = 1;
|
||||||
|
ul_bwp1_locationAndBandwidth = 28875; // RBstart=0, L=106 (40 MHz BW)
|
||||||
|
# subcarrierSpacing
|
||||||
|
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||||
|
ul_bwp1_subcarrierSpacing = 1;
|
||||||
|
|
||||||
|
# BWP 2 Configuration
|
||||||
|
ul_bwp-Id_2 = 2;
|
||||||
|
ul_bwp2_locationAndBandwidth = 13750; // RBstart=0, L=51 (20 MHz BW)
|
||||||
|
# subcarrierSpacing
|
||||||
|
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||||
|
ul_bwp2_subcarrierSpacing = 1;
|
||||||
|
|
||||||
|
# BWP 3 Configuration
|
||||||
|
ul_bwp-Id_3 = 3;
|
||||||
|
ul_bwp3_locationAndBandwidth = 6325; // RBstart=0, L=24 (10 MHz BW)
|
||||||
|
# subcarrierSpacing
|
||||||
|
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||||
|
ul_bwp3_subcarrierSpacing = 1;
|
||||||
|
|
||||||
|
firstActiveUplinkBWP-Id = 1; #BWP-Id
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
# ------- 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"; });
|
||||||
|
|
||||||
|
|
||||||
|
NETWORK_INTERFACES : {
|
||||||
|
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129";
|
||||||
|
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129";
|
||||||
|
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
MACRLCs = (
|
||||||
|
{
|
||||||
|
num_cc = 1;
|
||||||
|
tr_s_preference = "local_L1";
|
||||||
|
tr_n_preference = "local_RRC";
|
||||||
|
pusch_TargetSNRx10 = 250;
|
||||||
|
pucch_TargetSNRx10 = 200;
|
||||||
|
ulsch_max_frame_inactivity = 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
L1s = (
|
||||||
|
{
|
||||||
|
num_cc = 1;
|
||||||
|
tr_n_preference = "local_mac";
|
||||||
|
prach_dtx_threshold = 120;
|
||||||
|
pucch0_dtx_threshold = 100;
|
||||||
|
ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
RUs = ({
|
||||||
|
local_rf = "yes";
|
||||||
|
nb_tx = 1;
|
||||||
|
nb_rx = 1;
|
||||||
|
att_tx = 0;
|
||||||
|
att_rx = 0;
|
||||||
|
bands = [78];
|
||||||
|
max_pdschReferenceSignalPower = -27;
|
||||||
|
max_rxgain = 114;
|
||||||
|
eNB_instances = [0];
|
||||||
|
#beamforming 1x4 matrix:
|
||||||
|
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
|
||||||
|
clock_src = "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";
|
||||||
|
nr_rrc_log_level ="info";
|
||||||
|
rrc_log_level ="info";
|
||||||
|
ngap_log_level ="debug";
|
||||||
|
f1ap_log_level ="debug";
|
||||||
|
};
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
neighbour_list = (
|
||||||
|
{
|
||||||
|
nr_cellid = 1;
|
||||||
|
neighbour_cell_configuration = (
|
||||||
|
{
|
||||||
|
gNB_ID = 0xb00;
|
||||||
|
nr_cellid = 2;
|
||||||
|
physical_cellId = 0x002;
|
||||||
|
absoluteFrequencySSB = 641280 ;
|
||||||
|
subcarrierSpacing = 1; #30 KHz
|
||||||
|
plmn = { mcc = 216; mnc = 03; mnc_length = 2};
|
||||||
|
tracking_area_code = 2;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gNB_ID = 0xa00;
|
||||||
|
nr_cellid = 3;
|
||||||
|
physical_cellId = 0x003;
|
||||||
|
absoluteFrequencySSB = 641280 ;
|
||||||
|
subcarrierSpacing = 1; #30 KHz
|
||||||
|
plmn = { mcc = 999; mnc = 99; mnc_length = 2};
|
||||||
|
tracking_area_code = 3;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gNB_ID = 0xc00;
|
||||||
|
nr_cellid = 4;
|
||||||
|
physical_cellId = 0x004;
|
||||||
|
absoluteFrequencySSB = 641280 ;
|
||||||
|
subcarrierSpacing = 1; #30 KHz
|
||||||
|
plmn = { mcc = 999; mnc = 99; mnc_length = 2};
|
||||||
|
tracking_area_code = 4;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nr_cellid = 2;
|
||||||
|
neighbour_cell_configuration = (
|
||||||
|
{
|
||||||
|
gNB_ID = 0xe00;
|
||||||
|
nr_cellid = 1;
|
||||||
|
physical_cellId = 0x000;
|
||||||
|
absoluteFrequencySSB = 641280 ;
|
||||||
|
subcarrierSpacing = 1; #30 KHz
|
||||||
|
plmn = { mcc = 001; mnc = 01; mnc_length = 2};
|
||||||
|
tracking_area_code = 1;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
nr_measurement_configuration = {
|
||||||
|
Periodical = {
|
||||||
|
enable = 1;
|
||||||
|
includeBeamMeasurements = 1;
|
||||||
|
maxNrofRS_IndexesToReport = 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
A2 = {
|
||||||
|
enable = 1;
|
||||||
|
threshold = 60;
|
||||||
|
timeToTrigger = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
A3 = ({
|
||||||
|
cell_id = -1; #Default
|
||||||
|
offset = 10;
|
||||||
|
hysteresis = 0;
|
||||||
|
timeToTrigger = 1
|
||||||
|
}, {
|
||||||
|
cell_id = 2;
|
||||||
|
offset = 5;
|
||||||
|
hysteresis = 1;
|
||||||
|
timeToTrigger = 2
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
@@ -85,6 +85,7 @@
|
|||||||
#include "NR_EUTRA-MBSFN-SubframeConfig.h"
|
#include "NR_EUTRA-MBSFN-SubframeConfig.h"
|
||||||
#include "uper_decoder.h"
|
#include "uper_decoder.h"
|
||||||
#include "uper_encoder.h"
|
#include "uper_encoder.h"
|
||||||
|
#include "common/utils/ds/seq_arr.h"
|
||||||
|
|
||||||
#include "RRC/NR/MESSAGES/asn1_msg.h"
|
#include "RRC/NR/MESSAGES/asn1_msg.h"
|
||||||
#include "RRC/NR/nr_rrc_extern.h"
|
#include "RRC/NR/nr_rrc_extern.h"
|
||||||
@@ -1515,6 +1516,155 @@ void config_security(gNB_RRC_INST *rrc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sort_neighbour_cell_config_by_cell_id(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const neighbour_cell_configuration_t *config_a = (const neighbour_cell_configuration_t *)a;
|
||||||
|
const neighbour_cell_configuration_t *config_b = (const neighbour_cell_configuration_t *)b;
|
||||||
|
|
||||||
|
if (config_a->nr_cell_id < config_b->nr_cell_id) {
|
||||||
|
return -1;
|
||||||
|
} else if (config_a->nr_cell_id > config_b->nr_cell_id) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fill_neighbour_cell_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
|
||||||
|
{
|
||||||
|
char gnbpath[MAX_OPTNAME_SIZE + 8];
|
||||||
|
sprintf(gnbpath, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx);
|
||||||
|
|
||||||
|
paramdef_t neighbour_list_params[] = GNB_NEIGHBOUR_LIST_PARAM_LIST;
|
||||||
|
paramlist_def_t neighbour_list_param_list = {GNB_CONFIG_STRING_NEIGHBOUR_LIST, NULL, 0};
|
||||||
|
|
||||||
|
config_getlist(config_get_if(), &neighbour_list_param_list, neighbour_list_params, sizeofArray(neighbour_list_params), gnbpath);
|
||||||
|
if (neighbour_list_param_list.numelt < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rrc->neighbour_cell_configuration = malloc(sizeof(seq_arr_t));
|
||||||
|
seq_arr_init(rrc->neighbour_cell_configuration, sizeof(neighbour_cell_configuration_t));
|
||||||
|
|
||||||
|
for (int elm = 0; elm < neighbour_list_param_list.numelt; ++elm) {
|
||||||
|
neighbour_cell_configuration_t *cell = calloc(1, sizeof(neighbour_cell_configuration_t));
|
||||||
|
AssertFatal(cell != NULL, "out of memory\n");
|
||||||
|
cell->nr_cell_id = (uint64_t)*neighbour_list_param_list.paramarray[elm][0].u64ptr;
|
||||||
|
|
||||||
|
char neighbourpath[MAX_OPTNAME_SIZE + 8];
|
||||||
|
sprintf(neighbourpath, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, gnb_idx, GNB_CONFIG_STRING_NEIGHBOUR_LIST, elm);
|
||||||
|
paramdef_t NeighbourCellParams[] = GNBNEIGHBOURCELLPARAMS_DESC;
|
||||||
|
paramlist_def_t NeighbourCellParamList = {GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST, NULL, 0};
|
||||||
|
config_getlist(config_get_if(), &NeighbourCellParamList, NeighbourCellParams, sizeofArray(NeighbourCellParams), neighbourpath);
|
||||||
|
LOG_D(GNB_APP, "HO LOG: For the Cell: %d Neighbour Cell ELM NUM: %d\n", cell->nr_cell_id, NeighbourCellParamList.numelt);
|
||||||
|
if (NeighbourCellParamList.numelt < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cell->neighbour_cells = malloc(sizeof(seq_arr_t));
|
||||||
|
AssertFatal(cell->neighbour_cells != NULL, "Memory exhausted!!!");
|
||||||
|
seq_arr_init(cell->neighbour_cells, sizeof(nr_neighbour_gnb_configuration_t));
|
||||||
|
for (int l = 0; l < NeighbourCellParamList.numelt; ++l) {
|
||||||
|
nr_neighbour_gnb_configuration_t *neighbourCell = calloc(1, sizeof(nr_neighbour_gnb_configuration_t));
|
||||||
|
AssertFatal(neighbourCell != NULL, "out of memory\n");
|
||||||
|
neighbourCell->gNB_ID = *(NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_GNB_ID_IDX].uptr);
|
||||||
|
neighbourCell->nrcell_id = (uint64_t) * (NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_NR_CELLID_IDX].u64ptr);
|
||||||
|
neighbourCell->physicalCellId = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX].uptr;
|
||||||
|
neighbourCell->subcarrierSpacing = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_SCS_IDX].uptr;
|
||||||
|
neighbourCell->absoluteFrequencySSB = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX].i64ptr;
|
||||||
|
neighbourCell->tac = *NeighbourCellParamList.paramarray[l][GNB_CONFIG_N_CELL_TAC_IDX].uptr;
|
||||||
|
|
||||||
|
char neighbour_plmn_path[CONFIG_MAXOPTLENGTH];
|
||||||
|
sprintf(neighbour_plmn_path,
|
||||||
|
"%s.%s.[%i].%s",
|
||||||
|
neighbourpath,
|
||||||
|
GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST,
|
||||||
|
l,
|
||||||
|
GNB_CONFIG_STRING_NEIGHBOUR_PLMN);
|
||||||
|
|
||||||
|
paramdef_t NeighbourPlmn[] = GNBPLMNPARAMS_DESC;
|
||||||
|
config_get(config_get_if(), NeighbourPlmn, sizeofArray(NeighbourPlmn), neighbour_plmn_path);
|
||||||
|
|
||||||
|
neighbourCell->plmn.mcc = *NeighbourPlmn[GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
|
||||||
|
neighbourCell->plmn.mnc = *NeighbourPlmn[GNB_MOBILE_NETWORK_CODE_IDX].uptr;
|
||||||
|
neighbourCell->plmn.mnc_digit_length = *NeighbourPlmn[GNB_MNC_DIGIT_LENGTH].uptr;
|
||||||
|
seq_arr_push_back(cell->neighbour_cells, neighbourCell, sizeof(nr_neighbour_gnb_configuration_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_arr_push_back(rrc->neighbour_cell_configuration, cell, sizeof(neighbour_cell_configuration_t));
|
||||||
|
}
|
||||||
|
void *base = seq_arr_front(rrc->neighbour_cell_configuration);
|
||||||
|
size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration);
|
||||||
|
size_t element_size = sizeof(neighbour_cell_configuration_t);
|
||||||
|
|
||||||
|
qsort(base, nmemb, element_size, sort_neighbour_cell_config_by_cell_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fill_measurement_configuration(uint8_t gnb_idx, gNB_RRC_INST *rrc)
|
||||||
|
{
|
||||||
|
char measurement_path[MAX_OPTNAME_SIZE + 8];
|
||||||
|
sprintf(measurement_path, "%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, gnb_idx, GNB_CONFIG_STRING_MEASUREMENT_CONFIGURATION);
|
||||||
|
|
||||||
|
nr_measurement_configuration_t *measurementConfig = &rrc->measurementConfiguration;
|
||||||
|
// Periodical Event Configuration
|
||||||
|
char periodic_event_path[MAX_OPTNAME_SIZE + 8];
|
||||||
|
sprintf(periodic_event_path,
|
||||||
|
"%s.[%i].%s.%s",
|
||||||
|
GNB_CONFIG_STRING_GNB_LIST,
|
||||||
|
gnb_idx,
|
||||||
|
GNB_CONFIG_STRING_MEASUREMENT_CONFIGURATION,
|
||||||
|
MEASUREMENT_EVENTS_PERIODICAL);
|
||||||
|
paramdef_t Periodical_EventParams[] = MEASUREMENT_PERIODICAL_GLOBALPARAMS_DESC;
|
||||||
|
config_get(config_get_if(), Periodical_EventParams, sizeofArray(Periodical_EventParams), periodic_event_path);
|
||||||
|
if (*Periodical_EventParams[MEASUREMENT_EVENTS_ENABLE_IDX].i64ptr) {
|
||||||
|
nr_per_event_t *periodic_event = (nr_per_event_t *)calloc(1, sizeof(nr_per_event_t));
|
||||||
|
periodic_event->includeBeamMeasurements = *Periodical_EventParams[MEASUREMENT_EVENTS_INCLUDE_BEAM_MEAS_IDX].i64ptr;
|
||||||
|
periodic_event->maxReportCells = *Periodical_EventParams[MEASUREMENT_EVENTS_MAX_RS_INDEX_TO_REPORT].i64ptr;
|
||||||
|
|
||||||
|
measurementConfig->per_event = periodic_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A2 Event Configuration
|
||||||
|
char a2_path[MAX_OPTNAME_SIZE + 8];
|
||||||
|
sprintf(a2_path,
|
||||||
|
"%s.[%i].%s.%s",
|
||||||
|
GNB_CONFIG_STRING_GNB_LIST,
|
||||||
|
gnb_idx,
|
||||||
|
GNB_CONFIG_STRING_MEASUREMENT_CONFIGURATION,
|
||||||
|
MEASUREMENT_EVENTS_A2);
|
||||||
|
paramdef_t A2_EventParams[] = MEASUREMENT_A2_GLOBALPARAMS_DESC;
|
||||||
|
config_get(config_get_if(), A2_EventParams, sizeofArray(A2_EventParams), a2_path);
|
||||||
|
if (*A2_EventParams[MEASUREMENT_EVENTS_ENABLE_IDX].i64ptr) {
|
||||||
|
nr_a2_event_t *a2_event = (nr_a2_event_t *)calloc(1, sizeof(nr_a2_event_t));
|
||||||
|
a2_event->threshold_RSRP = *A2_EventParams[MEASUREMENT_EVENTS_A2_THRESHOLD_IDX].i64ptr;
|
||||||
|
a2_event->timeToTrigger = *A2_EventParams[MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX].i64ptr;
|
||||||
|
|
||||||
|
measurementConfig->a2_event = a2_event;
|
||||||
|
}
|
||||||
|
// A3 Event Configuration
|
||||||
|
paramlist_def_t A3_EventList = {MEASUREMENT_EVENTS_A3, NULL, 0};
|
||||||
|
paramdef_t A3_EventParams[] = MEASUREMENT_A3_GLOBALPARAMS_DESC;
|
||||||
|
config_getlist(config_get_if(), &A3_EventList, A3_EventParams, sizeofArray(A3_EventParams), measurement_path);
|
||||||
|
LOG_D(GNB_APP, "HO LOG: A3 Configuration Exists: %d\n", A3_EventList.numelt);
|
||||||
|
|
||||||
|
if (A3_EventList.numelt < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
measurementConfig->a3_event_list = malloc(sizeof(seq_arr_t));
|
||||||
|
seq_arr_init(measurementConfig->a3_event_list, sizeof(nr_a3_event_t));
|
||||||
|
for (int i = 0; i < A3_EventList.numelt; i++) {
|
||||||
|
nr_a3_event_t *a3_event = (nr_a3_event_t *)calloc(1, sizeof(nr_a3_event_t));
|
||||||
|
AssertFatal(a3_event != NULL, "out of memory\n");
|
||||||
|
a3_event->cell_id = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_CELL_ID_IDX].i64ptr;
|
||||||
|
a3_event->timeToTrigger = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX].i64ptr;
|
||||||
|
a3_event->a3_offset = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_OFFSET_IDX].i64ptr;
|
||||||
|
a3_event->hysteresis = *A3_EventList.paramarray[i][MEASUREMENT_EVENTS_HYSTERESIS_IDX].i64ptr;
|
||||||
|
|
||||||
|
if (a3_event->cell_id == -1)
|
||||||
|
measurementConfig->is_default_a3_configuration_exists = true;
|
||||||
|
|
||||||
|
seq_arr_push_back(measurementConfig->a3_event_list, a3_event, sizeof(nr_a3_event_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RCconfig_NRRRC(gNB_RRC_INST *rrc)
|
void RCconfig_NRRRC(gNB_RRC_INST *rrc)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -1604,7 +1754,10 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
|
|||||||
char gnbpath[MAX_OPTNAME_SIZE + 8];
|
char gnbpath[MAX_OPTNAME_SIZE + 8];
|
||||||
sprintf(gnbpath,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k);
|
sprintf(gnbpath,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k);
|
||||||
|
|
||||||
|
fill_neighbour_cell_configuration(k, rrc);
|
||||||
|
|
||||||
|
fill_measurement_configuration(k, rrc);
|
||||||
|
|
||||||
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
|
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
|
||||||
|
|
||||||
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
|
||||||
|
|||||||
@@ -254,7 +254,92 @@ typedef enum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Neighbour Cell Configurations*/
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_LIST "neighbour_list"
|
||||||
|
// clang-format off
|
||||||
|
#define GNB_NEIGHBOUR_LIST_PARAM_LIST { \
|
||||||
|
/* optname helpstr paramflags XXXptr def val type numelt */ \
|
||||||
|
{GNB_CONFIG_STRING_NRCELLID, "cell nrCell Id which has neighbours", PARAMFLAG_MANDATORY, .u64ptr=NULL, .defint64val=0, TYPE_UINT64, 0}, \
|
||||||
|
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID, "neighbour cell physical id", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_LIST "neighbour_cell_configuration"
|
||||||
|
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_GNB_ID "gNB_ID"
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_NR_CELLID "nr_cellid"
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID "physical_cellId"
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB "absoluteFrequencySSB"
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS "subcarrierSpacing"
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE "tracking_area_code"
|
||||||
|
#define GNB_CONFIG_STRING_NEIGHBOUR_PLMN "plmn"
|
||||||
|
|
||||||
|
#define GNB_CONFIG_N_CELL_GNB_ID_IDX 0
|
||||||
|
#define GNB_CONFIG_N_CELL_NR_CELLID_IDX 1
|
||||||
|
#define GNB_CONFIG_N_CELL_PHYSICAL_ID_IDX 2
|
||||||
|
#define GNB_CONFIG_N_CELL_ABS_FREQ_SSB_IDX 3
|
||||||
|
#define GNB_CONFIG_N_CELL_SCS_IDX 4
|
||||||
|
#define GNB_CONFIG_N_CELL_TAC_IDX 5
|
||||||
|
// clang-format off
|
||||||
|
#define GNBNEIGHBOURCELLPARAMS_DESC { \
|
||||||
|
/* optname helpstr paramflags XXXptr def val type numelt */ \
|
||||||
|
{GNB_CONFIG_STRING_GNB_ID, "neighbour cell's gNB ID", PARAMFLAG_MANDATORY, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
|
||||||
|
{GNB_CONFIG_STRING_NRCELLID, "neighbour cell nrCell Id", PARAMFLAG_MANDATORY, .u64ptr=NULL, .defint64val=0, TYPE_UINT64, 0}, \
|
||||||
|
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_PHYSICAL_ID, "neighbour cell physical id", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
|
||||||
|
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_ABS_FREQ_SSB, "neighbour cell abs freq ssb", PARAMFLAG_MANDATORY, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0}, \
|
||||||
|
{GNB_CONFIG_STRING_NEIGHBOUR_CELL_SCS, "neighbour cell scs", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
|
||||||
|
{GNB_CONFIG_STRING_NEIGHBOUR_TRACKING_ARE_CODE, "neighbour cell tracking area", PARAMFLAG_MANDATORY, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
/* New Measurement Configurations*/
|
||||||
|
|
||||||
|
#define GNB_CONFIG_STRING_MEASUREMENT_CONFIGURATION "nr_measurement_configuration"
|
||||||
|
#define MEASUREMENT_EVENTS_PERIODICAL "Periodical"
|
||||||
|
#define MEASUREMENT_EVENTS_A2 "A2"
|
||||||
|
#define MEASUREMENT_EVENTS_A3 "A3"
|
||||||
|
|
||||||
|
#define MEASUREMENT_EVENTS_OFFSET "offset"
|
||||||
|
#define MEASUREMENT_EVENTS_HYSTERESIS "hysteresis"
|
||||||
|
#define MEASUREMENT_EVENTS_TIME_TO_TRIGGER "time_to_trigger"
|
||||||
|
#define MEASUREMENT_EVENTS_THRESHOLD "threshold"
|
||||||
|
#define MEASUREMENT_EVENTS_PERIODICAL_BEAM_MEASUREMENT "includeBeamMeasurements"
|
||||||
|
#define MEASUREMENT_EVENTS_PERIODICAL_NR_OF_RS_INDEXES "maxNrofRS_IndexesToReport"
|
||||||
|
#define MEASUREMENT_EVENTS_CELL_ID "cell_id"
|
||||||
|
#define MEASUREMENT_EVENT_ENABLE "enable"
|
||||||
|
// clang-format off
|
||||||
|
#define MEASUREMENT_A3_GLOBALPARAMS_DESC \
|
||||||
|
{ \
|
||||||
|
{MEASUREMENT_EVENTS_CELL_ID, "neighbour cellId for A3Report", 0, .i64ptr = NULL, .defint64val = -1, TYPE_INT64, 0}, \
|
||||||
|
{MEASUREMENT_EVENTS_TIME_TO_TRIGGER, "a3 time to trigger", 0, .i64ptr = NULL, .defint64val = 1, TYPE_INT64, 0}, \
|
||||||
|
{MEASUREMENT_EVENTS_OFFSET, "a3 offset", 0, .i64ptr = NULL, .defint64val = 60, TYPE_INT64, 0}, \
|
||||||
|
{MEASUREMENT_EVENTS_HYSTERESIS, "a3 hysteresis", 0, .i64ptr = NULL, .defint64val = 0, TYPE_INT64, 0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MEASUREMENT_A2_GLOBALPARAMS_DESC \
|
||||||
|
{ \
|
||||||
|
{MEASUREMENT_EVENT_ENABLE, "enable the event", 0, .i64ptr = NULL, .defint64val = 1, TYPE_INT64, 0}, \
|
||||||
|
{MEASUREMENT_EVENTS_TIME_TO_TRIGGER, "a2 time to trigger", 0, .i64ptr = NULL, .defint64val = 1, TYPE_INT64, 0}, \
|
||||||
|
{MEASUREMENT_EVENTS_THRESHOLD, "a2 threshold", 0, .i64ptr = NULL, .defint64val = 60, TYPE_INT64, 0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MEASUREMENT_PERIODICAL_GLOBALPARAMS_DESC \
|
||||||
|
{ \
|
||||||
|
{MEASUREMENT_EVENT_ENABLE, "enable the event", 0, .i64ptr = NULL, .defint64val = 1, TYPE_INT64, 0}, \
|
||||||
|
{MEASUREMENT_EVENTS_PERIODICAL_BEAM_MEASUREMENT, "includeBeamMeasurements", PARAMFLAG_BOOL, .i64ptr = NULL, .defint64val = 1, TYPE_INT64, 0}, \
|
||||||
|
{MEASUREMENT_EVENTS_PERIODICAL_NR_OF_RS_INDEXES, "maxNrofRS_IndexesToReport", 0, .i64ptr = NULL, .defint64val = 4, TYPE_INT64, 0}, \
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#define MEASUREMENT_EVENTS_CELL_ID_IDX 0
|
||||||
|
#define MEASUREMENT_EVENTS_ENABLE_IDX 0
|
||||||
|
#define MEASUREMENT_EVENTS_TIMETOTRIGGER_IDX 1
|
||||||
|
#define MEASUREMENT_EVENTS_A2_THRESHOLD_IDX 2
|
||||||
|
#define MEASUREMENT_EVENTS_OFFSET_IDX 2
|
||||||
|
#define MEASUREMENT_EVENTS_HYSTERESIS_IDX 3
|
||||||
|
#define MEASUREMENT_EVENTS_INCLUDE_BEAM_MEAS_IDX 1
|
||||||
|
#define MEASUREMENT_EVENTS_MAX_RS_INDEX_TO_REPORT 2
|
||||||
|
|
||||||
/* PLMN ID configuration */
|
/* PLMN ID configuration */
|
||||||
|
|
||||||
|
|||||||
@@ -736,7 +736,7 @@ int do_RRCReconfiguration(const gNB_RRC_UE_t *UE,
|
|||||||
|
|
||||||
dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration = ie;
|
dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration = ie;
|
||||||
|
|
||||||
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
|
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
|
||||||
xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg);
|
xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1093,15 +1093,180 @@ int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t r
|
|||||||
return((enc_rval.encoded+7)/8);
|
return((enc_rval.encoded+7)/8);
|
||||||
}
|
}
|
||||||
|
|
||||||
NR_MeasConfig_t *get_defaultMeasConfig(const NR_MeasTiming_t *mt, int band, int scs)
|
static NR_ReportConfigToAddMod_t *prepare_periodic_event_report(const nr_per_event_t *per_event)
|
||||||
{
|
{
|
||||||
DevAssert(mt != NULL && mt->frequencyAndTiming != NULL);
|
NR_ReportConfigToAddMod_t *rc = calloc(1, sizeof(*rc));
|
||||||
const struct NR_MeasTiming__frequencyAndTiming *ft = mt->frequencyAndTiming;
|
rc->reportConfigId = 1;
|
||||||
const NR_SSB_MTC_t *ssb_mtc = &ft->ssb_MeasurementTimingConfiguration;
|
rc->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
|
||||||
|
|
||||||
|
NR_PeriodicalReportConfig_t *prc = calloc(1, sizeof(*prc));
|
||||||
|
prc->rsType = NR_NR_RS_Type_ssb;
|
||||||
|
prc->reportInterval = NR_ReportInterval_ms1024;
|
||||||
|
prc->reportAmount = NR_PeriodicalReportConfig__reportAmount_infinity;
|
||||||
|
prc->reportQuantityCell.rsrp = true;
|
||||||
|
prc->reportQuantityCell.rsrq = true;
|
||||||
|
prc->reportQuantityCell.sinr = true;
|
||||||
|
prc->reportQuantityRS_Indexes = calloc(1, sizeof(*prc->reportQuantityRS_Indexes));
|
||||||
|
prc->reportQuantityRS_Indexes->rsrp = true;
|
||||||
|
prc->reportQuantityRS_Indexes->rsrq = true;
|
||||||
|
prc->reportQuantityRS_Indexes->sinr = true;
|
||||||
|
asn1cCallocOne(prc->maxNrofRS_IndexesToReport, per_event->maxReportCells);
|
||||||
|
prc->maxReportCells = per_event->maxReportCells;
|
||||||
|
prc->includeBeamMeasurements = per_event->includeBeamMeasurements;
|
||||||
|
|
||||||
|
NR_ReportConfigNR_t *rcnr = calloc(1, sizeof(*rcnr));
|
||||||
|
rcnr->reportType.present = NR_ReportConfigNR__reportType_PR_periodical;
|
||||||
|
rcnr->reportType.choice.periodical = prc;
|
||||||
|
|
||||||
|
rc->reportConfig.choice.reportConfigNR = rcnr;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NR_ReportConfigToAddMod_t *prepare_a2_event_report(const nr_a2_event_t *a2_event)
|
||||||
|
{
|
||||||
|
NR_ReportConfigToAddMod_t *rc_A2 = calloc(1, sizeof(*rc_A2));
|
||||||
|
rc_A2->reportConfigId = 2;
|
||||||
|
rc_A2->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
|
||||||
|
NR_EventTriggerConfig_t *etrc_A2 = calloc(1, sizeof(*etrc_A2));
|
||||||
|
etrc_A2->eventId.present = NR_EventTriggerConfig__eventId_PR_eventA2;
|
||||||
|
etrc_A2->eventId.choice.eventA2 = calloc(1, sizeof(*etrc_A2->eventId.choice.eventA2));
|
||||||
|
etrc_A2->eventId.choice.eventA2->a2_Threshold.present = NR_MeasTriggerQuantity_PR_rsrp;
|
||||||
|
etrc_A2->eventId.choice.eventA2->a2_Threshold.choice.rsrp = a2_event->threshold_RSRP;
|
||||||
|
etrc_A2->eventId.choice.eventA2->reportOnLeave = false;
|
||||||
|
etrc_A2->eventId.choice.eventA2->hysteresis = 0;
|
||||||
|
etrc_A2->eventId.choice.eventA2->timeToTrigger = a2_event->timeToTrigger;
|
||||||
|
etrc_A2->rsType = NR_NR_RS_Type_ssb;
|
||||||
|
etrc_A2->reportInterval = NR_ReportInterval_ms480;
|
||||||
|
etrc_A2->reportAmount = NR_EventTriggerConfig__reportAmount_r4;
|
||||||
|
etrc_A2->reportQuantityCell.rsrp = true;
|
||||||
|
etrc_A2->reportQuantityCell.rsrq = true;
|
||||||
|
etrc_A2->reportQuantityCell.sinr = true;
|
||||||
|
asn1cCallocOne(etrc_A2->maxNrofRS_IndexesToReport, 4);
|
||||||
|
etrc_A2->maxReportCells = 1;
|
||||||
|
etrc_A2->includeBeamMeasurements = false;
|
||||||
|
NR_ReportConfigNR_t *rcnr_A2 = calloc(1, sizeof(*rcnr_A2));
|
||||||
|
rcnr_A2->reportType.present = NR_ReportConfigNR__reportType_PR_eventTriggered;
|
||||||
|
rcnr_A2->reportType.choice.eventTriggered = etrc_A2;
|
||||||
|
rc_A2->reportConfig.choice.reportConfigNR = rcnr_A2;
|
||||||
|
|
||||||
|
return rc_A2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a3_event)
|
||||||
|
{
|
||||||
|
NR_ReportConfigToAddMod_t *rc_A3 = calloc(1, sizeof(*rc_A3));
|
||||||
|
rc_A3->reportConfigId =
|
||||||
|
a3_event->cell_id == -1
|
||||||
|
? 3
|
||||||
|
: a3_event->cell_id + 4; // 3 is default A3 Report Config ID. So cellId(0) specific Report Config ID starts from 4
|
||||||
|
rc_A3->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
|
||||||
|
NR_EventTriggerConfig_t *etrc_A3 = calloc(1, sizeof(*etrc_A3));
|
||||||
|
etrc_A3->eventId.present = NR_EventTriggerConfig__eventId_PR_eventA3;
|
||||||
|
etrc_A3->eventId.choice.eventA3 = calloc(1, sizeof(*etrc_A3->eventId.choice.eventA3));
|
||||||
|
etrc_A3->eventId.choice.eventA3->a3_Offset.present = NR_MeasTriggerQuantityOffset_PR_rsrp;
|
||||||
|
etrc_A3->eventId.choice.eventA3->a3_Offset.choice.rsrp = a3_event->a3_offset;
|
||||||
|
etrc_A3->eventId.choice.eventA3->reportOnLeave = true;
|
||||||
|
etrc_A3->eventId.choice.eventA3->hysteresis = a3_event->hysteresis;
|
||||||
|
etrc_A3->eventId.choice.eventA3->timeToTrigger = a3_event->timeToTrigger;
|
||||||
|
etrc_A3->rsType = NR_NR_RS_Type_ssb;
|
||||||
|
etrc_A3->reportInterval = NR_ReportInterval_ms1024;
|
||||||
|
etrc_A3->reportAmount = NR_EventTriggerConfig__reportAmount_r4;
|
||||||
|
etrc_A3->reportQuantityCell.rsrp = true;
|
||||||
|
etrc_A3->reportQuantityCell.rsrq = true;
|
||||||
|
etrc_A3->reportQuantityCell.sinr = true;
|
||||||
|
asn1cCallocOne(etrc_A3->maxNrofRS_IndexesToReport, 4);
|
||||||
|
etrc_A3->maxReportCells = 4;
|
||||||
|
etrc_A3->includeBeamMeasurements = false;
|
||||||
|
NR_ReportConfigNR_t *rcnr_A3 = calloc(1, sizeof(*rcnr_A3));
|
||||||
|
rcnr_A3->reportType.present = NR_ReportConfigNR__reportType_PR_eventTriggered;
|
||||||
|
rcnr_A3->reportType.choice.eventTriggered = etrc_A3;
|
||||||
|
rc_A3->reportConfig.choice.reportConfigNR = rcnr_A3;
|
||||||
|
return rc_A3;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nr_a3_event_t *get_a3_configuration(int nr_cellid)
|
||||||
|
{
|
||||||
|
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||||
|
nr_measurement_configuration_t *measurementConfiguration = &rrc->measurementConfiguration;
|
||||||
|
if (!measurementConfiguration->a3_event_list)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < measurementConfiguration->a3_event_list->size; i++) {
|
||||||
|
nr_a3_event_t *a3_event = (nr_a3_event_t *)seq_arr_at(measurementConfiguration->a3_event_list, i);
|
||||||
|
if (a3_event->cell_id == nr_cellid)
|
||||||
|
return a3_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (measurementConfiguration->is_default_a3_configuration_exists)
|
||||||
|
return get_a3_configuration(-1);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt,
|
||||||
|
int band,
|
||||||
|
int scs,
|
||||||
|
const nr_measurement_configuration_t *const measurementConfiguration,
|
||||||
|
const seq_arr_t *const neighbourConfiguration)
|
||||||
|
{
|
||||||
|
if (!measurementConfiguration)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!measurementConfiguration->a2_event && !measurementConfiguration->per_event && !measurementConfiguration->a3_event_list) {
|
||||||
|
LOG_D(NR_RRC, "NR Measurements are not configured in the conf file\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!measurementConfiguration->a2_event && !measurementConfiguration->per_event && measurementConfiguration->a3_event_list
|
||||||
|
&& !neighbourConfiguration) {
|
||||||
|
LOG_I(NR_RRC, "A2 and Periodical Events are off. A3 Can not be prepared without neighbours!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
NR_MeasConfig_t *mc = calloc(1, sizeof(*mc));
|
NR_MeasConfig_t *mc = calloc(1, sizeof(*mc));
|
||||||
mc->measObjectToAddModList = calloc(1, sizeof(*mc->measObjectToAddModList));
|
mc->measObjectToAddModList = calloc(1, sizeof(*mc->measObjectToAddModList));
|
||||||
mc->reportConfigToAddModList = calloc(1, sizeof(*mc->reportConfigToAddModList));
|
mc->reportConfigToAddModList = calloc(1, sizeof(*mc->reportConfigToAddModList));
|
||||||
|
mc->measIdToAddModList = calloc(1, sizeof(*mc->measIdToAddModList));
|
||||||
|
|
||||||
|
if (measurementConfiguration->per_event) {
|
||||||
|
NR_ReportConfigToAddMod_t *rc_PER = prepare_periodic_event_report(measurementConfiguration->per_event);
|
||||||
|
asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_PER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (measurementConfiguration->a2_event) {
|
||||||
|
LOG_D(NR_RRC, "HO LOG: Preparing A2 Event Measurement Configuration!\n");
|
||||||
|
NR_ReportConfigToAddMod_t *rc_A2 = prepare_a2_event_report(measurementConfiguration->a2_event);
|
||||||
|
asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (neighbourConfiguration && measurementConfiguration->a3_event_list && measurementConfiguration->a3_event_list->size > 0) {
|
||||||
|
/* Loop through neighbours and find related A3 configuration
|
||||||
|
If no related A3 but there is default add the default one.
|
||||||
|
If default one added once as a report, no need to add it again && duplication.
|
||||||
|
*/
|
||||||
|
LOG_D(NR_RRC, "HO LOG: Preparing A3 Event Measurement Configuration!\n");
|
||||||
|
bool is_default_a3_added = false;
|
||||||
|
for (uint8_t neighbourIdx = 0; neighbourIdx < neighbourConfiguration->size; neighbourIdx++) {
|
||||||
|
const nr_neighbour_gnb_configuration_t *neighbourCell =
|
||||||
|
(const nr_neighbour_gnb_configuration_t *)seq_arr_at(neighbourConfiguration, neighbourIdx);
|
||||||
|
if (!neighbourCell->isIntraFrequencyNeighbour)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const nr_a3_event_t *a3Event = get_a3_configuration(neighbourCell->nrcell_id);
|
||||||
|
if (!a3Event || is_default_a3_added)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (a3Event->cell_id == -1)
|
||||||
|
is_default_a3_added = true;
|
||||||
|
|
||||||
|
NR_ReportConfigToAddMod_t *rc_A3 = prepare_a3_event_report(a3Event);
|
||||||
|
asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc_A3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DevAssert(mt != NULL && mt->frequencyAndTiming != NULL);
|
||||||
|
const struct NR_MeasTiming__frequencyAndTiming *ft = mt->frequencyAndTiming;
|
||||||
|
const NR_SSB_MTC_t *ssb_mtc = &ft->ssb_MeasurementTimingConfiguration;
|
||||||
|
|
||||||
// Measurement Objects: Specifies what is to be measured. For NR and inter-RAT E-UTRA measurements, this may include
|
// Measurement Objects: Specifies what is to be measured. For NR and inter-RAT E-UTRA measurements, this may include
|
||||||
// cell-specific offsets, blacklisted cells to be ignored and whitelisted cells to consider for measurements.
|
// cell-specific offsets, blacklisted cells to be ignored and whitelisted cells to consider for measurements.
|
||||||
@@ -1122,62 +1287,48 @@ NR_MeasConfig_t *get_defaultMeasConfig(const NR_MeasTiming_t *mt, int band, int
|
|||||||
monr1->quantityConfigIndex = 1;
|
monr1->quantityConfigIndex = 1;
|
||||||
monr1->ext1 = calloc(1, sizeof(*monr1->ext1));
|
monr1->ext1 = calloc(1, sizeof(*monr1->ext1));
|
||||||
asn1cCallocOne(monr1->ext1->freqBandIndicatorNR, band);
|
asn1cCallocOne(monr1->ext1->freqBandIndicatorNR, band);
|
||||||
|
|
||||||
|
if (neighbourConfiguration && measurementConfiguration->a3_event_list) {
|
||||||
|
for (uint8_t nCell = 0; nCell < neighbourConfiguration->size; nCell++) {
|
||||||
|
const nr_neighbour_gnb_configuration_t *neighbourCell =
|
||||||
|
(const nr_neighbour_gnb_configuration_t *)seq_arr_at(neighbourConfiguration, nCell);
|
||||||
|
if (!neighbourCell->isIntraFrequencyNeighbour)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (monr1->cellsToAddModList == NULL) {
|
||||||
|
monr1->cellsToAddModList = calloc(1, sizeof(*monr1->cellsToAddModList));
|
||||||
|
}
|
||||||
|
|
||||||
|
NR_CellsToAddMod_t *cell = calloc(1, sizeof(*cell));
|
||||||
|
cell->physCellId = neighbourCell->physicalCellId;
|
||||||
|
ASN_SEQUENCE_ADD(&monr1->cellsToAddModList->list, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mo1->measObject.choice.measObjectNR = monr1;
|
mo1->measObject.choice.measObjectNR = monr1;
|
||||||
asn1cSeqAdd(&mc->measObjectToAddModList->list, mo1);
|
asn1cSeqAdd(&mc->measObjectToAddModList->list, mo1);
|
||||||
|
|
||||||
// Reporting Configuration: Specifies how reporting should be done. This could be periodic or event-triggered.
|
|
||||||
NR_ReportConfigToAddMod_t *rc = calloc(1, sizeof(*rc));
|
|
||||||
rc->reportConfigId = 1;
|
|
||||||
rc->reportConfig.present = NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
|
|
||||||
|
|
||||||
NR_PeriodicalReportConfig_t *prc = calloc(1, sizeof(*prc));
|
// Preparation of measId
|
||||||
prc->rsType = NR_NR_RS_Type_ssb;
|
for (uint8_t reportIdx = 0; reportIdx < mc->reportConfigToAddModList->list.count; reportIdx++) {
|
||||||
prc->reportInterval = NR_ReportInterval_ms1024;
|
const NR_ReportConfigId_t reportId = mc->reportConfigToAddModList->list.array[reportIdx]->reportConfigId;
|
||||||
prc->reportAmount = NR_PeriodicalReportConfig__reportAmount_infinity;
|
NR_MeasIdToAddMod_t *measid = calloc(1, sizeof(NR_MeasIdToAddMod_t));
|
||||||
prc->reportQuantityCell.rsrp = true;
|
measid->measId = reportIdx + 1;
|
||||||
prc->reportQuantityCell.rsrq = true;
|
measid->reportConfigId = reportId;
|
||||||
prc->reportQuantityCell.sinr = true;
|
measid->measObjectId = 1;
|
||||||
prc->reportQuantityRS_Indexes = calloc(1, sizeof(*prc->reportQuantityRS_Indexes));
|
asn1cSeqAdd(&mc->measIdToAddModList->list, measid);
|
||||||
prc->reportQuantityRS_Indexes->rsrp = true;
|
}
|
||||||
prc->reportQuantityRS_Indexes->rsrq = true;
|
|
||||||
prc->reportQuantityRS_Indexes->sinr = true;
|
|
||||||
asn1cCallocOne(prc->maxNrofRS_IndexesToReport, 4);
|
|
||||||
prc->maxReportCells = 4;
|
|
||||||
prc->includeBeamMeasurements = true;
|
|
||||||
|
|
||||||
NR_ReportConfigNR_t *rcnr = calloc(1, sizeof(*rcnr));
|
|
||||||
rcnr->reportType.present = NR_ReportConfigNR__reportType_PR_periodical;
|
|
||||||
rcnr->reportType.choice.periodical = prc;
|
|
||||||
|
|
||||||
|
|
||||||
rc->reportConfig.choice.reportConfigNR = rcnr;
|
|
||||||
asn1cSeqAdd(&mc->reportConfigToAddModList->list, rc);
|
|
||||||
|
|
||||||
// Measurement ID: Identifies how to report measurements of a specific object. This is a many-to-many mapping: a
|
|
||||||
// measurement object could have multiple reporting configurations, a reporting configuration could apply to multiple
|
|
||||||
// objects. A unique ID is used for each object-to-report-config association. When UE sends a MeasurementReport
|
|
||||||
// message, a single ID and related measurements are included in the message.
|
|
||||||
mc->measIdToAddModList = calloc(1, sizeof(*mc->measIdToAddModList));
|
|
||||||
NR_MeasIdToAddMod_t *measid = calloc(1, sizeof(*measid));
|
|
||||||
measid->measId = 1;
|
|
||||||
measid->measObjectId = 1;
|
|
||||||
measid->reportConfigId = 1;
|
|
||||||
asn1cSeqAdd(&mc->measIdToAddModList->list, measid);
|
|
||||||
|
|
||||||
// Quantity Configuration: Specifies parameters for layer 3 filtering of measurements. Only after filtering, reporting
|
|
||||||
// criteria are evaluated. The formula used is F_n = (1-a)F_(n-1) + a*M_n, where M is the latest measurement, F is the
|
|
||||||
// filtered measurement, and ais based on configured filter coefficient.
|
|
||||||
mc->quantityConfig = calloc(1, sizeof(*mc->quantityConfig));
|
mc->quantityConfig = calloc(1, sizeof(*mc->quantityConfig));
|
||||||
mc->quantityConfig->quantityConfigNR_List = calloc(1, sizeof(*mc->quantityConfig->quantityConfigNR_List));
|
mc->quantityConfig->quantityConfigNR_List = calloc(1, sizeof(*mc->quantityConfig->quantityConfigNR_List));
|
||||||
NR_QuantityConfigNR_t *qcnr3 = calloc(1, sizeof(*qcnr3));
|
NR_QuantityConfigNR_t *qcnr = calloc(1, sizeof(*qcnr));
|
||||||
asn1cCallocOne(qcnr3->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6);
|
asn1cCallocOne(qcnr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6);
|
||||||
asn1cCallocOne(qcnr3->quantityConfigCell.csi_RS_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6);
|
asn1cCallocOne(qcnr->quantityConfigCell.csi_RS_FilterConfig.filterCoefficientRSRP, NR_FilterCoefficient_fc6);
|
||||||
asn1cSeqAdd(&mc->quantityConfig->quantityConfigNR_List->list, qcnr3);
|
asn1cSeqAdd(&mc->quantityConfig->quantityConfigNR_List->list, qcnr);
|
||||||
|
|
||||||
return mc;
|
return mc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_defaultMeasConfig(NR_MeasConfig_t *mc)
|
void free_MeasConfig(NR_MeasConfig_t *mc)
|
||||||
{
|
{
|
||||||
ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, mc);
|
ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, mc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,8 +143,13 @@ int do_RRCReestablishment(rrc_gNB_ue_context_t *const ue_context_pP,
|
|||||||
|
|
||||||
int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier);
|
int do_RRCReestablishmentComplete(uint8_t *buffer, size_t buffer_size, int64_t rrc_TransactionIdentifier);
|
||||||
|
|
||||||
NR_MeasConfig_t *get_defaultMeasConfig(const NR_MeasTiming_t *mt, int band, int scs);
|
const nr_a3_event_t *get_a3_configuration(int nr_cellid);
|
||||||
void free_defaultMeasConfig(NR_MeasConfig_t *mc);
|
NR_MeasConfig_t *get_MeasConfig(const NR_MeasTiming_t *mt,
|
||||||
|
int band,
|
||||||
|
int scs,
|
||||||
|
const nr_measurement_configuration_t *const measurementConfiguration,
|
||||||
|
const seq_arr_t *const neighbourConfiguration);
|
||||||
|
void free_MeasConfig(NR_MeasConfig_t *mc);
|
||||||
int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi);
|
int do_NR_Paging(uint8_t Mod_id, uint8_t *buffer, uint32_t tmsi);
|
||||||
|
|
||||||
#endif /* __RRC_NR_MESSAGES_ASN1_MSG__H__ */
|
#endif /* __RRC_NR_MESSAGES_ASN1_MSG__H__ */
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include "collection/tree.h"
|
#include "collection/tree.h"
|
||||||
#include "collection/linear_alloc.h"
|
#include "collection/linear_alloc.h"
|
||||||
|
#include "common/utils/ds/seq_arr.h"
|
||||||
#include "nr_rrc_common.h"
|
#include "nr_rrc_common.h"
|
||||||
#include "ds/byte_array.h"
|
#include "ds/byte_array.h"
|
||||||
|
|
||||||
@@ -359,6 +360,46 @@ typedef struct {
|
|||||||
int do_drb_integrity;
|
int do_drb_integrity;
|
||||||
} nr_security_configuration_t;
|
} nr_security_configuration_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long maxReportCells;
|
||||||
|
bool includeBeamMeasurements;
|
||||||
|
} nr_per_event_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long threshold_RSRP;
|
||||||
|
long timeToTrigger;
|
||||||
|
} nr_a2_event_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int cell_id;
|
||||||
|
long a3_offset;
|
||||||
|
long hysteresis;
|
||||||
|
long timeToTrigger;
|
||||||
|
} nr_a3_event_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
nr_per_event_t *per_event;
|
||||||
|
nr_a2_event_t *a2_event;
|
||||||
|
seq_arr_t *a3_event_list;
|
||||||
|
bool is_default_a3_configuration_exists;
|
||||||
|
} nr_measurement_configuration_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t gNB_ID;
|
||||||
|
uint64_t nrcell_id;
|
||||||
|
int physicalCellId;
|
||||||
|
int absoluteFrequencySSB;
|
||||||
|
int subcarrierSpacing;
|
||||||
|
plmn_identity_t plmn;
|
||||||
|
uint32_t tac;
|
||||||
|
bool isIntraFrequencyNeighbour;
|
||||||
|
} nr_neighbour_gnb_configuration_t;
|
||||||
|
|
||||||
|
typedef struct neighbour_cell_configuration_s {
|
||||||
|
int nr_cell_id;
|
||||||
|
seq_arr_t *neighbour_cells;
|
||||||
|
} neighbour_cell_configuration_t;
|
||||||
|
|
||||||
typedef struct nr_mac_rrc_dl_if_s {
|
typedef struct nr_mac_rrc_dl_if_s {
|
||||||
f1_setup_response_func_t f1_setup_response;
|
f1_setup_response_func_t f1_setup_response;
|
||||||
f1_setup_failure_func_t f1_setup_failure;
|
f1_setup_failure_func_t f1_setup_failure;
|
||||||
@@ -423,6 +464,8 @@ typedef struct gNB_RRC_INST_s {
|
|||||||
|
|
||||||
nr_mac_rrc_dl_if_t mac_rrc;
|
nr_mac_rrc_dl_if_t mac_rrc;
|
||||||
cucp_cuup_if_t cucp_cuup;
|
cucp_cuup_if_t cucp_cuup;
|
||||||
|
seq_arr_t *neighbour_cell_configuration;
|
||||||
|
nr_measurement_configuration_t measurementConfiguration;
|
||||||
|
|
||||||
RB_HEAD(rrc_du_tree, nr_rrc_du_container_t) dus; // DUs, indexed by assoc_id
|
RB_HEAD(rrc_du_tree, nr_rrc_du_container_t) dus; // DUs, indexed by assoc_id
|
||||||
size_t num_dus;
|
size_t num_dus;
|
||||||
|
|||||||
+187
-28
@@ -141,6 +141,42 @@ static void freeDRBlist(NR_DRB_ToAddModList_t *list)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const neighbour_cell_configuration_t *get_neighbour_config(int serving_cell_nr_cellid)
|
||||||
|
{
|
||||||
|
const gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||||
|
seq_arr_t *neighbour_cell_configuration = rrc->neighbour_cell_configuration;
|
||||||
|
if (!neighbour_cell_configuration)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (int cellIdx = 0; cellIdx < neighbour_cell_configuration->size; cellIdx++) {
|
||||||
|
neighbour_cell_configuration_t *neighbour_config =
|
||||||
|
(neighbour_cell_configuration_t *)seq_arr_at(neighbour_cell_configuration, cellIdx);
|
||||||
|
if (neighbour_config->nr_cell_id == serving_cell_nr_cellid)
|
||||||
|
return neighbour_config;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nr_neighbour_gnb_configuration_t *get_neighbour_cell_information(int serving_cell_nr_cellid, int neighbour_cell_phy_id)
|
||||||
|
{
|
||||||
|
const gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||||
|
seq_arr_t *neighbour_cell_configuration = rrc->neighbour_cell_configuration;
|
||||||
|
for (int cellIdx = 0; cellIdx < neighbour_cell_configuration->size; cellIdx++) {
|
||||||
|
neighbour_cell_configuration_t *neighbour_config =
|
||||||
|
(neighbour_cell_configuration_t *)seq_arr_at(neighbour_cell_configuration, cellIdx);
|
||||||
|
if (!neighbour_config)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int neighbourIdx = 0; neighbourIdx < neighbour_config->neighbour_cells->size; neighbourIdx++) {
|
||||||
|
nr_neighbour_gnb_configuration_t *neighbour =
|
||||||
|
(nr_neighbour_gnb_configuration_t *)seq_arr_at(neighbour_config->neighbour_cells, neighbourIdx);
|
||||||
|
if (neighbour != NULL && neighbour->physicalCellId == neighbour_cell_phy_id)
|
||||||
|
return neighbour;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct deliver_dl_rrc_message_data_s {
|
typedef struct deliver_dl_rrc_message_data_s {
|
||||||
const gNB_RRC_INST *rrc;
|
const gNB_RRC_INST *rrc;
|
||||||
f1ap_dl_rrc_message_t *dl_rrc;
|
f1ap_dl_rrc_message_t *dl_rrc;
|
||||||
@@ -176,24 +212,6 @@ void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc,
|
|||||||
&data);
|
&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_dl_band(const f1ap_served_cell_info_t *cell_info)
|
|
||||||
{
|
|
||||||
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.freqinfo.band : cell_info->fdd.dl_freqinfo.band;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_ssb_scs(const f1ap_served_cell_info_t *cell_info)
|
|
||||||
{
|
|
||||||
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.scs : cell_info->fdd.dl_tbw.scs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_ssb_arfcn(const nr_rrc_du_container_t *du)
|
|
||||||
{
|
|
||||||
DevAssert(du != NULL && du->mtc != NULL);
|
|
||||||
/* format has been verified when accepting MeasurementTimingConfiguration */
|
|
||||||
NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
|
|
||||||
return mtlist->list.array[0]->frequencyAndTiming->carrierFreq;
|
|
||||||
}
|
|
||||||
|
|
||||||
///---------------------------------------------------------------------------------------------------------------///
|
///---------------------------------------------------------------------------------------------------------------///
|
||||||
///---------------------------------------------------------------------------------------------------------------///
|
///---------------------------------------------------------------------------------------------------------------///
|
||||||
|
|
||||||
@@ -522,14 +540,25 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
|
|||||||
DevAssert(du != NULL);
|
DevAssert(du != NULL);
|
||||||
f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
|
f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
|
||||||
NR_MeasConfig_t *measconfig = NULL;
|
NR_MeasConfig_t *measconfig = NULL;
|
||||||
|
|
||||||
if (du->mtc != NULL) {
|
if (du->mtc != NULL) {
|
||||||
int scs = get_ssb_scs(cell_info);
|
int scs = get_ssb_scs(cell_info);
|
||||||
int band = get_dl_band(cell_info);
|
int band = get_dl_band(cell_info);
|
||||||
const NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
|
const NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
|
||||||
const NR_MeasTiming_t *mt = mtlist->list.array[0];
|
const NR_MeasTiming_t *mt = mtlist->list.array[0];
|
||||||
measconfig = get_defaultMeasConfig(mt, band, scs);
|
const neighbour_cell_configuration_t *neighbour_config = get_neighbour_config(cell_info->nr_cellid);
|
||||||
|
seq_arr_t *neighbour_cells = NULL;
|
||||||
|
if (neighbour_config)
|
||||||
|
neighbour_cells = neighbour_config->neighbour_cells;
|
||||||
|
|
||||||
|
measconfig = get_MeasConfig(mt, band, scs, &rrc->measurementConfiguration, neighbour_cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ue_p->measConfig)
|
||||||
|
free_MeasConfig(ue_p->measConfig);
|
||||||
|
|
||||||
|
ue_p->measConfig = measconfig;
|
||||||
|
|
||||||
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
uint8_t buffer[RRC_BUF_SIZE] = {0};
|
||||||
NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false);
|
NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, false);
|
||||||
NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false);
|
NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, false);
|
||||||
@@ -545,8 +574,7 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const c
|
|||||||
measconfig,
|
measconfig,
|
||||||
dedicatedNAS_MessageList,
|
dedicatedNAS_MessageList,
|
||||||
cellGroupConfig);
|
cellGroupConfig);
|
||||||
LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n");
|
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n");
|
||||||
free_defaultMeasConfig(measconfig);
|
|
||||||
freeSRBlist(SRBs);
|
freeSRBlist(SRBs);
|
||||||
freeDRBlist(DRBs);
|
freeDRBlist(DRBs);
|
||||||
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, ue_p->DRB_ReleaseList);
|
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, ue_p->DRB_ReleaseList);
|
||||||
@@ -1166,14 +1194,9 @@ fallback_rrc_setup:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context, NR_MeasurementReport_t *measurementReport)
|
static void process_Periodical_Measurement_Report(rrc_gNB_ue_context_t *ue_context, NR_MeasurementReport_t *measurementReport)
|
||||||
{
|
{
|
||||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
// LOG_I(NR_RRC, "Periodical Event Report! Do Nothing for now...\n");
|
||||||
xer_fprint(stdout, &asn_DEF_NR_MeasurementReport, (void *)measurementReport);
|
|
||||||
|
|
||||||
DevAssert(measurementReport->criticalExtensions.present == NR_MeasurementReport__criticalExtensions_PR_measurementReport
|
|
||||||
&& measurementReport->criticalExtensions.choice.measurementReport != NULL);
|
|
||||||
|
|
||||||
gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context;
|
gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context;
|
||||||
ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, ue_ctxt->measResults);
|
ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, ue_ctxt->measResults);
|
||||||
ue_ctxt->measResults = NULL;
|
ue_ctxt->measResults = NULL;
|
||||||
@@ -1186,6 +1209,141 @@ static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context,
|
|||||||
measurementReport->criticalExtensions.choice.measurementReport = NULL;
|
measurementReport->criticalExtensions.choice.measurementReport = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void process_Event_Based_Measurement_Report(NR_ReportConfigNR_t *report, NR_MeasurementReport_t *measurementReport)
|
||||||
|
{
|
||||||
|
NR_EventTriggerConfig_t *event_triggered = report->reportType.choice.eventTriggered;
|
||||||
|
|
||||||
|
int servingCellRSRP = 0;
|
||||||
|
int neighbourCellRSRP = 0;
|
||||||
|
int servingCellId = -1;
|
||||||
|
|
||||||
|
switch (event_triggered->eventId.present) {
|
||||||
|
case NR_EventTriggerConfig__eventId_PR_eventA2:
|
||||||
|
LOG_I(NR_RRC, "\nHO LOG: Event A2 (Serving becomes worse than threshold)\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NR_EventTriggerConfig__eventId_PR_eventA3: {
|
||||||
|
LOG_I(NR_RRC, "\nHO LOG: Event A3 Report - Neighbour Becomes Better than Serving!\n");
|
||||||
|
const NR_MeasResults_t *measResults = &measurementReport->criticalExtensions.choice.measurementReport->measResults;
|
||||||
|
|
||||||
|
for (int serving_cell_idx = 0; serving_cell_idx < measResults->measResultServingMOList.list.count; serving_cell_idx++) {
|
||||||
|
const NR_MeasResultServMO_t *meas_result_serv_MO = measResults->measResultServingMOList.list.array[serving_cell_idx];
|
||||||
|
servingCellId = *(meas_result_serv_MO->measResultServingCell.physCellId);
|
||||||
|
if (meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell) {
|
||||||
|
servingCellRSRP = *(meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsSSB_Cell->rsrp) - 157;
|
||||||
|
} else {
|
||||||
|
servingCellRSRP = *(meas_result_serv_MO->measResultServingCell.measResult.cellResults.resultsCSI_RS_Cell->rsrp) - 157;
|
||||||
|
}
|
||||||
|
LOG_D(NR_RRC, "Serving Cell RSRP: %d\n", servingCellRSRP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (measResults->measResultNeighCells == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (measResults->measResultNeighCells->present != NR_MeasResults__measResultNeighCells_PR_measResultListNR)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const NR_MeasResultListNR_t *measResultListNR = measResults->measResultNeighCells->choice.measResultListNR;
|
||||||
|
for (int neigh_meas_idx = 0; neigh_meas_idx < measResultListNR->list.count; neigh_meas_idx++) {
|
||||||
|
const NR_MeasResultNR_t *meas_result_neigh_cell = (measResultListNR->list.array[neigh_meas_idx]);
|
||||||
|
const int neighbourCellId = *(meas_result_neigh_cell->physCellId);
|
||||||
|
|
||||||
|
// TS 138 133 Table 10.1.6.1-1: SS-RSRP and CSI-RSRP measurement report mapping
|
||||||
|
const struct NR_MeasResultNR__measResult__cellResults *cellResults = &(meas_result_neigh_cell->measResult.cellResults);
|
||||||
|
|
||||||
|
if (cellResults->resultsSSB_Cell) {
|
||||||
|
neighbourCellRSRP = *(cellResults->resultsSSB_Cell->rsrp) - 157;
|
||||||
|
} else {
|
||||||
|
neighbourCellRSRP = *(cellResults->resultsCSI_RS_Cell->rsrp) - 157;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_I(NR_RRC,
|
||||||
|
"HO LOG: Measurement Report has came for the neighbour: %d with RSRP: %d\n",
|
||||||
|
neighbourCellId,
|
||||||
|
neighbourCellRSRP);
|
||||||
|
|
||||||
|
const f1ap_served_cell_info_t *neighbour_cell_du_context = get_cell_information_by_phycellId(neighbourCellId);
|
||||||
|
const f1ap_served_cell_info_t *serving_cell_du_context = get_cell_information_by_phycellId(servingCellId);
|
||||||
|
const nr_neighbour_gnb_configuration_t *neighbour =
|
||||||
|
get_neighbour_cell_information(serving_cell_du_context->nr_cellid, neighbourCellId);
|
||||||
|
// CU does not have f1 connection with neighbour cell context. So check does serving cell has this phyCellId as a
|
||||||
|
// neighbour.
|
||||||
|
if (!neighbour_cell_du_context && neighbour) {
|
||||||
|
// No F1 connection but static neighbour configuration is available
|
||||||
|
const nr_a3_event_t *a3_event_configuration = get_a3_configuration(neighbour->nrcell_id);
|
||||||
|
// Additional check - This part can be modified according to additional cell specific Handover Margin
|
||||||
|
if (a3_event_configuration
|
||||||
|
&& ((a3_event_configuration->a3_offset + a3_event_configuration->hysteresis)
|
||||||
|
< (neighbourCellRSRP - servingCellRSRP))) {
|
||||||
|
LOG_D(NR_RRC, "HO LOG: Trigger N2 HO for the neighbour gnb: %u cell: %lu\n", neighbour->gNB_ID, neighbour->nrcell_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
LOG_D(NR_RRC, "NR_EventTriggerConfig__eventId_PR_NOTHING or Other event report\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rrc_gNB_process_MeasurementReport(rrc_gNB_ue_context_t *ue_context, NR_MeasurementReport_t *measurementReport)
|
||||||
|
{
|
||||||
|
LOG_D(NR_RRC, "Process Measurement Report\n");
|
||||||
|
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||||
|
xer_fprint(stdout, &asn_DEF_NR_MeasurementReport, (void *)measurementReport);
|
||||||
|
|
||||||
|
DevAssert(measurementReport->criticalExtensions.present == NR_MeasurementReport__criticalExtensions_PR_measurementReport
|
||||||
|
&& measurementReport->criticalExtensions.choice.measurementReport != NULL);
|
||||||
|
|
||||||
|
gNB_RRC_UE_t *ue_ctxt = &ue_context->ue_context;
|
||||||
|
NR_MeasConfig_t *meas_config = ue_ctxt->measConfig;
|
||||||
|
if (meas_config == NULL) {
|
||||||
|
LOG_I(NR_RRC, "Unexpected Measurement Report from UE with id: %d\n", ue_ctxt->rrc_ue_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NR_MeasurementReport_IEs_t *measurementReport_IEs = measurementReport->criticalExtensions.choice.measurementReport;
|
||||||
|
const NR_MeasId_t measId = measurementReport_IEs->measResults.measId;
|
||||||
|
|
||||||
|
NR_MeasIdToAddMod_t *meas_id_s = NULL;
|
||||||
|
for (int meas_idx = 0; meas_idx < meas_config->measIdToAddModList->list.count; meas_idx++) {
|
||||||
|
if (measId == meas_config->measIdToAddModList->list.array[meas_idx]->measId) {
|
||||||
|
meas_id_s = meas_config->measIdToAddModList->list.array[meas_idx];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meas_id_s == NULL) {
|
||||||
|
LOG_E(NR_RRC, "Incoming Meas ID with id: %d Can not Found!\n", (int)measId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_D(NR_RRC, "HO LOG: Meas Id is found: %d\n", (int)meas_id_s->measId);
|
||||||
|
|
||||||
|
struct NR_ReportConfigToAddMod__reportConfig *report_config = NULL;
|
||||||
|
for (int rep_id = 0; rep_id < meas_config->reportConfigToAddModList->list.count; rep_id++) {
|
||||||
|
if (meas_id_s->reportConfigId == meas_config->reportConfigToAddModList->list.array[rep_id]->reportConfigId) {
|
||||||
|
report_config = &meas_config->reportConfigToAddModList->list.array[rep_id]->reportConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report_config == NULL) {
|
||||||
|
LOG_E(NR_RRC, "There is no related report configuration for this measId!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (report_config->choice.reportConfigNR->reportType.present == NR_ReportConfigNR__reportType_PR_periodical)
|
||||||
|
return process_Periodical_Measurement_Report(ue_context, measurementReport);
|
||||||
|
|
||||||
|
if (report_config->choice.reportConfigNR->reportType.present != NR_ReportConfigNR__reportType_PR_eventTriggered) {
|
||||||
|
LOG_D(NR_RRC, "Incoming Report Type: %d is not supported! \n", report_config->choice.reportConfigNR->reportType.present);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
process_Event_Based_Measurement_Report(report_config->choice.reportConfigNR, measurementReport);
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP,
|
static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP,
|
||||||
rrc_gNB_ue_context_t *ue_context_p,
|
rrc_gNB_ue_context_t *ue_context_p,
|
||||||
const NR_RRCReestablishmentComplete_t *reestablishment_complete)
|
const NR_RRCReestablishmentComplete_t *reestablishment_complete)
|
||||||
@@ -1801,6 +1959,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE)
|
|||||||
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
|
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr);
|
||||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
|
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
|
||||||
ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, UE->measResults);
|
ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, UE->measResults);
|
||||||
|
free_MeasConfig(UE->measConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p)
|
void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p)
|
||||||
|
|||||||
@@ -27,7 +27,26 @@
|
|||||||
#include "openair2/F1AP/f1ap_common.h"
|
#include "openair2/F1AP/f1ap_common.h"
|
||||||
#include "openair2/F1AP/f1ap_ids.h"
|
#include "openair2/F1AP/f1ap_ids.h"
|
||||||
#include "executables/softmodem-common.h"
|
#include "executables/softmodem-common.h"
|
||||||
|
#include "common/utils/ds/seq_arr.h"
|
||||||
|
#include "common/utils/alg/foreach.h"
|
||||||
|
|
||||||
|
int get_dl_band(const struct f1ap_served_cell_info_t *cell_info)
|
||||||
|
{
|
||||||
|
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.freqinfo.band : cell_info->fdd.dl_freqinfo.band;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_ssb_scs(const struct f1ap_served_cell_info_t *cell_info)
|
||||||
|
{
|
||||||
|
return cell_info->mode == F1AP_MODE_TDD ? cell_info->tdd.tbw.scs : cell_info->fdd.dl_tbw.scs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_ssb_arfcn(const struct nr_rrc_du_container_t *du)
|
||||||
|
{
|
||||||
|
DevAssert(du != NULL && du->mtc != NULL);
|
||||||
|
/* format has been verified when accepting MeasurementTimingConfiguration */
|
||||||
|
NR_MeasTimingList_t *mtlist = du->mtc->criticalExtensions.choice.c1->choice.measTimingConf->measTiming;
|
||||||
|
return mtlist->list.array[0]->frequencyAndTiming->carrierFreq;
|
||||||
|
}
|
||||||
|
|
||||||
static int du_compare(const nr_rrc_du_container_t *a, const nr_rrc_du_container_t *b)
|
static int du_compare(const nr_rrc_du_container_t *a, const nr_rrc_du_container_t *b)
|
||||||
{
|
{
|
||||||
@@ -104,6 +123,80 @@ static NR_MeasurementTimingConfiguration_t *extract_mtc(uint8_t *buf, int buf_le
|
|||||||
return mtc;
|
return mtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nr_cell_id_match(const void *key, const void *element)
|
||||||
|
{
|
||||||
|
const int *key_id = (const int *)key;
|
||||||
|
const neighbour_cell_configuration_t *config_element = (const neighbour_cell_configuration_t *)element;
|
||||||
|
|
||||||
|
if (*key_id < config_element->nr_cell_id) {
|
||||||
|
return -1;
|
||||||
|
} else if (*key_id == config_element->nr_cell_id) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static neighbour_cell_configuration_t *get_cell_neighbour_list(const gNB_RRC_INST *rrc, const f1ap_served_cell_info_t *cell_info)
|
||||||
|
{
|
||||||
|
void *base = seq_arr_front(rrc->neighbour_cell_configuration);
|
||||||
|
size_t nmemb = seq_arr_size(rrc->neighbour_cell_configuration);
|
||||||
|
size_t size = sizeof(neighbour_cell_configuration_t);
|
||||||
|
|
||||||
|
void *it = bsearch((void *)&cell_info->nr_cellid, base, nmemb, size, nr_cell_id_match);
|
||||||
|
|
||||||
|
return (neighbour_cell_configuration_t *)it;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct f1ap_served_cell_info_t *get_cell_information_by_phycellId(int phyCellId)
|
||||||
|
{
|
||||||
|
gNB_RRC_INST *rrc = RC.nrrrc[0];
|
||||||
|
nr_rrc_du_container_t *it = NULL;
|
||||||
|
RB_FOREACH (it, rrc_du_tree, &rrc->dus) {
|
||||||
|
for (int cellIdx = 0; cellIdx < it->setup_req->num_cells_available; cellIdx++) {
|
||||||
|
const f1ap_served_cell_info_t *cell_info = &(it->setup_req->cell[cellIdx].info);
|
||||||
|
if (cell_info->nr_pci == phyCellId) {
|
||||||
|
LOG_D(NR_RRC, "HO LOG: Found cell with phyCellId %d\n", phyCellId);
|
||||||
|
return cell_info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void is_intra_frequency_neighbour(void *ssb_arfcn, void *neighbour_cell)
|
||||||
|
{
|
||||||
|
uint32_t *ssb_arfcn_ptr = (uint32_t *)ssb_arfcn;
|
||||||
|
nr_neighbour_gnb_configuration_t *neighbour_cell_ptr = (nr_neighbour_gnb_configuration_t *)neighbour_cell;
|
||||||
|
|
||||||
|
if (*ssb_arfcn_ptr == neighbour_cell_ptr->absoluteFrequencySSB) {
|
||||||
|
LOG_D(NR_RRC, "HO LOG: found intra frequency neighbour %lu!\n", neighbour_cell_ptr->nrcell_id);
|
||||||
|
neighbour_cell_ptr->isIntraFrequencyNeighbour = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Labels neighbour cells if they are intra frequency to prepare meas config only for intra frequency ho
|
||||||
|
* @param[in] rrc Pointer to RRC instance
|
||||||
|
* @param[in] cell_info Pointer to cell information
|
||||||
|
*/
|
||||||
|
static void label_intra_frequency_neighbours(gNB_RRC_INST *rrc,
|
||||||
|
const nr_rrc_du_container_t *du,
|
||||||
|
const f1ap_served_cell_info_t *cell_info)
|
||||||
|
{
|
||||||
|
if (!rrc->neighbour_cell_configuration)
|
||||||
|
return;
|
||||||
|
|
||||||
|
neighbour_cell_configuration_t *neighbour_cell_config = get_cell_neighbour_list(rrc, cell_info);
|
||||||
|
if (!neighbour_cell_config)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG_D(NR_RRC, "HO LOG: Cell: %lu has neighbour cell configuration!\n", cell_info->nr_cellid);
|
||||||
|
uint32_t ssb_arfcn = get_ssb_arfcn(du);
|
||||||
|
|
||||||
|
seq_arr_t *cell_neighbour_list = neighbour_cell_config->neighbour_cells;
|
||||||
|
for_each(cell_neighbour_list, (void *)&ssb_arfcn, is_intra_frequency_neighbour);
|
||||||
|
}
|
||||||
|
|
||||||
void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||||
{
|
{
|
||||||
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
|
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
|
||||||
@@ -212,6 +305,9 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
|||||||
.num_SI = 0,
|
.num_SI = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (du->mib != NULL && du->sib1 != NULL)
|
||||||
|
label_intra_frequency_neighbours(rrc, du, cell_info);
|
||||||
|
|
||||||
f1ap_setup_resp_t resp = {.transaction_id = req->transaction_id,
|
f1ap_setup_resp_t resp = {.transaction_id = req->transaction_id,
|
||||||
.num_cells_to_activate = 1,
|
.num_cells_to_activate = 1,
|
||||||
.cells_to_activate[0] = cell};
|
.cells_to_activate[0] = cell};
|
||||||
@@ -333,6 +429,10 @@ void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update
|
|||||||
LOG_I(RRC, "update system information of DU %ld\n", du->setup_req->gNB_DU_id);
|
LOG_I(RRC, "update system information of DU %ld\n", du->setup_req->gNB_DU_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (du->mib != NULL && du->sib1 != NULL) {
|
||||||
|
const f1ap_served_cell_info_t *cell_info = &du->setup_req->cell[0].info;
|
||||||
|
label_intra_frequency_neighbours(rrc, du, cell_info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf_up->num_cells_to_delete > 0) {
|
if (conf_up->num_cells_to_delete > 0) {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ struct f1ap_lost_connection_t;
|
|||||||
struct gNB_RRC_INST_s;
|
struct gNB_RRC_INST_s;
|
||||||
struct nr_rrc_du_container_t;
|
struct nr_rrc_du_container_t;
|
||||||
struct f1ap_gnb_du_configuration_update_s;
|
struct f1ap_gnb_du_configuration_update_s;
|
||||||
|
struct f1ap_served_cell_info_t;
|
||||||
|
|
||||||
void rrc_gNB_process_f1_setup_req(struct f1ap_setup_req_s *req, sctp_assoc_t assoc_id);
|
void rrc_gNB_process_f1_setup_req(struct f1ap_setup_req_s *req, sctp_assoc_t assoc_id);
|
||||||
void rrc_CU_process_f1_lost_connection(struct gNB_RRC_INST_s *rrc, struct f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id);
|
void rrc_CU_process_f1_lost_connection(struct gNB_RRC_INST_s *rrc, struct f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id);
|
||||||
@@ -39,7 +40,12 @@ void rrc_gNB_process_f1_du_configuration_update(struct f1ap_gnb_du_configuration
|
|||||||
|
|
||||||
struct nr_rrc_du_container_t *get_du_for_ue(struct gNB_RRC_INST_s *rrc, uint32_t ue_id);
|
struct nr_rrc_du_container_t *get_du_for_ue(struct gNB_RRC_INST_s *rrc, uint32_t ue_id);
|
||||||
struct nr_rrc_du_container_t *get_du_by_assoc_id(struct gNB_RRC_INST_s *rrc, sctp_assoc_t assoc_id);
|
struct nr_rrc_du_container_t *get_du_by_assoc_id(struct gNB_RRC_INST_s *rrc, sctp_assoc_t assoc_id);
|
||||||
|
const struct f1ap_served_cell_info_t *get_cell_information_by_phycellId(int phyCellId);
|
||||||
|
|
||||||
void dump_du_info(const struct gNB_RRC_INST_s *rrc, FILE *f);
|
void dump_du_info(const struct gNB_RRC_INST_s *rrc, FILE *f);
|
||||||
|
|
||||||
|
int get_dl_band(const struct f1ap_served_cell_info_t *cell_info);
|
||||||
|
int get_ssb_scs(const struct f1ap_served_cell_info_t *cell_info);
|
||||||
|
int get_ssb_arfcn(const struct nr_rrc_du_container_t *du);
|
||||||
|
|
||||||
#endif /* RRC_GNB_DU_H_ */
|
#endif /* RRC_GNB_DU_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user