Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
spbro
OpenXG-RAN
Commits
7db4732c
Commit
7db4732c
authored
Jun 04, 2024
by
Robert Schmidt
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/N2_HO_Measurement_config' into integration_2024_w22
parents
9465ae77
c51b2a64
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
1181 additions
and
82 deletions
+1181
-82
ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf
...ipts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf
+321
-0
ci-scripts/conf_files/neighbour-config.conf
ci-scripts/conf_files/neighbour-config.conf
+76
-0
openair2/GNB_APP/gnb_config.c
openair2/GNB_APP/gnb_config.c
+154
-1
openair2/GNB_APP/gnb_paramdef.h
openair2/GNB_APP/gnb_paramdef.h
+86
-1
openair2/RRC/NR/MESSAGES/asn1_msg.c
openair2/RRC/NR/MESSAGES/asn1_msg.c
+201
-50
openair2/RRC/NR/MESSAGES/asn1_msg.h
openair2/RRC/NR/MESSAGES/asn1_msg.h
+7
-2
openair2/RRC/NR/nr_rrc_defs.h
openair2/RRC/NR/nr_rrc_defs.h
+43
-0
openair2/RRC/NR/rrc_gNB.c
openair2/RRC/NR/rrc_gNB.c
+187
-28
openair2/RRC/NR/rrc_gNB_du.c
openair2/RRC/NR/rrc_gNB_du.c
+100
-0
openair2/RRC/NR/rrc_gNB_du.h
openair2/RRC/NR/rrc_gNB_du.h
+6
-0
No files found.
ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.neighbour.conf
0 → 100644
View file @
7db4732c
Active_gNBs
= (
"gNB-OAI"
);
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity
=
"none"
;
gNBs
=
(
{
//////////
Identification
parameters
:
gNB_ID
=
0
xe00
;
gNB_name
=
"gNB-OAI"
;
//
Tracking
area
code
,
0
x0000
and
0
xfffe
are
reserved
values
tracking_area_code
=
1
;
plmn_list
= ({
mcc
=
001
;
mnc
=
01
;
mnc_length
=
2
;
snssaiList
= ({
sst
=
1
;
sd
=
0
x1
; }) });
@
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
= [
0
x00007fff
,
0
x0000
,
0
x0000
,
0
x0000
];
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"
;
};
ci-scripts/conf_files/neighbour-config.conf
0 → 100644
View file @
7db4732c
neighbour_list
= (
{
nr_cellid
=
1
;
neighbour_cell_configuration
= (
{
gNB_ID
=
0
xb00
;
nr_cellid
=
2
;
physical_cellId
=
0
x002
;
absoluteFrequencySSB
=
641280
;
subcarrierSpacing
=
1
;
#30 KHz
plmn
= {
mcc
=
216
;
mnc
=
03
;
mnc_length
=
2
};
tracking_area_code
=
2
;
},
{
gNB_ID
=
0
xa00
;
nr_cellid
=
3
;
physical_cellId
=
0
x003
;
absoluteFrequencySSB
=
641280
;
subcarrierSpacing
=
1
;
#30 KHz
plmn
= {
mcc
=
999
;
mnc
=
99
;
mnc_length
=
2
};
tracking_area_code
=
3
;
},
{
gNB_ID
=
0
xc00
;
nr_cellid
=
4
;
physical_cellId
=
0
x004
;
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
=
0
xe00
;
nr_cellid
=
1
;
physical_cellId
=
0
x000
;
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
})
};
openair2/GNB_APP/gnb_config.c
View file @
7db4732c
...
...
@@ -85,6 +85,7 @@
#include "NR_EUTRA-MBSFN-SubframeConfig.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
#include "common/utils/ds/seq_arr.h"
#include "RRC/NR/MESSAGES/asn1_msg.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
)
{
...
...
@@ -1604,7 +1754,10 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
char
gnbpath
[
MAX_OPTNAME_SIZE
+
8
];
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
;
paramlist_def_t
PLMNParamList
=
{
GNB_CONFIG_STRING_PLMN_LIST
,
NULL
,
0
};
...
...
openair2/GNB_APP/gnb_paramdef.h
View file @
7db4732c
...
...
@@ -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 */
...
...
openair2/RRC/NR/MESSAGES/asn1_msg.c
View file @
7db4732c
...
...
@@ -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
;
if
(
LOG_DEBUGFLAG
(
DEBUG_ASN1
)
)
{
if
(
LOG_DEBUGFLAG
(
DEBUG_ASN1
)
)
{
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
);
}
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
);
const
struct
NR_MeasTiming__frequencyAndTiming
*
ft
=
mt
->
frequencyAndTiming
;
const
NR_SSB_MTC_t
*
ssb_mtc
=
&
ft
->
ssb_MeasurementTimingConfiguration
;
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
));
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
));
mc
->
measObjectToAddModList
=
calloc
(
1
,
sizeof
(
*
mc
->
measObjectToAddModList
));
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
// 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
->
ext1
=
calloc
(
1
,
sizeof
(
*
monr1
->
ext1
));
asn1cCallocOne
(
monr1
->
ext1
->
freqBandIndicatorNR
,
band
);
mo1
->
measObject
.
choice
.
measObjectNR
=
monr1
;
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
));
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
,
4
);
prc
->
maxReportCells
=
4
;
prc
->
includeBeamMeasurements
=
true
;
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
;
NR_ReportConfigNR_t
*
rcnr
=
calloc
(
1
,
sizeof
(
*
rcnr
));
rcnr
->
reportType
.
present
=
NR_ReportConfigNR__reportType_PR_periodical
;
rcnr
->
reportType
.
choice
.
periodical
=
prc
;
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
);
}
}
rc
->
reportConfig
.
choice
.
reportConfigNR
=
rcnr
;
asn1cSeqAdd
(
&
mc
->
reportConfigToAddModList
->
list
,
rc
);
mo1
->
measObject
.
choice
.
measObjectNR
=
monr1
;
asn1cSeqAdd
(
&
mc
->
measObjectToAddModList
->
list
,
mo1
);
// Preparation of measId
for
(
uint8_t
reportIdx
=
0
;
reportIdx
<
mc
->
reportConfigToAddModList
->
list
.
count
;
reportIdx
++
)
{
const
NR_ReportConfigId_t
reportId
=
mc
->
reportConfigToAddModList
->
list
.
array
[
reportIdx
]
->
reportConfigId
;
NR_MeasIdToAddMod_t
*
measid
=
calloc
(
1
,
sizeof
(
NR_MeasIdToAddMod_t
));
measid
->
measId
=
reportIdx
+
1
;
measid
->
reportConfigId
=
reportId
;
measid
->
measObjectId
=
1
;
asn1cSeqAdd
(
&
mc
->
measIdToAddModList
->
list
,
measid
);
}
// 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
->
quantityConfigNR_List
=
calloc
(
1
,
sizeof
(
*
mc
->
quantityConfig
->
quantityConfigNR_List
));
NR_QuantityConfigNR_t
*
qcnr
3
=
calloc
(
1
,
sizeof
(
*
qcnr3
));
asn1cCallocOne
(
qcnr
3
->
quantityConfigCell
.
ssb_FilterConfig
.
filterCoefficientRSRP
,
NR_FilterCoefficient_fc6
);
asn1cCallocOne
(
qcnr
3
->
quantityConfigCell
.
csi_RS_FilterConfig
.
filterCoefficientRSRP
,
NR_FilterCoefficient_fc6
);
asn1cSeqAdd
(
&
mc
->
quantityConfig
->
quantityConfigNR_List
->
list
,
qcnr
3
);
NR_QuantityConfigNR_t
*
qcnr
=
calloc
(
1
,
sizeof
(
*
qcnr
));
asn1cCallocOne
(
qcnr
->
quantityConfigCell
.
ssb_FilterConfig
.
filterCoefficientRSRP
,
NR_FilterCoefficient_fc6
);
asn1cCallocOne
(
qcnr
->
quantityConfigCell
.
csi_RS_FilterConfig
.
filterCoefficientRSRP
,
NR_FilterCoefficient_fc6
);
asn1cSeqAdd
(
&
mc
->
quantityConfig
->
quantityConfigNR_List
->
list
,
qcnr
);
return
mc
;
}
void
free_
default
MeasConfig
(
NR_MeasConfig_t
*
mc
)
void
free_MeasConfig
(
NR_MeasConfig_t
*
mc
)
{
ASN_STRUCT_FREE
(
asn_DEF_NR_MeasConfig
,
mc
);
}
...
...
openair2/RRC/NR/MESSAGES/asn1_msg.h
View file @
7db4732c
...
...
@@ -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
);
NR_MeasConfig_t
*
get_defaultMeasConfig
(
const
NR_MeasTiming_t
*
mt
,
int
band
,
int
scs
);
void
free_defaultMeasConfig
(
NR_MeasConfig_t
*
mc
);
const
nr_a3_event_t
*
get_a3_configuration
(
int
nr_cellid
);
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
);
#endif
/* __RRC_NR_MESSAGES_ASN1_MSG__H__ */
openair2/RRC/NR/nr_rrc_defs.h
View file @
7db4732c
...
...
@@ -37,6 +37,7 @@
#include "collection/tree.h"
#include "collection/linear_alloc.h"
#include "common/utils/ds/seq_arr.h"
#include "nr_rrc_common.h"
#include "ds/byte_array.h"
...
...
@@ -359,6 +360,46 @@ typedef struct {
int
do_drb_integrity
;
}
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
{
f1_setup_response_func_t
f1_setup_response
;
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
;
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
size_t
num_dus
;
...
...
openair2/RRC/NR/rrc_gNB.c
View file @
7db4732c
...
...
@@ -141,6 +141,42 @@ static void freeDRBlist(NR_DRB_ToAddModList_t *list)
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
{
const
gNB_RRC_INST
*
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
);
}
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
);
f1ap_served_cell_info_t
*
cell_info
=
&
du
->
setup_req
->
cell
[
0
].
info
;
NR_MeasConfig_t
*
measconfig
=
NULL
;
if
(
du
->
mtc
!=
NULL
)
{
int
scs
=
get_ssb_scs
(
cell_info
);
int
band
=
get_dl_band
(
cell_info
);
const
NR_MeasTimingList_t
*
mtlist
=
du
->
mtc
->
criticalExtensions
.
choice
.
c1
->
choice
.
measTimingConf
->
measTiming
;
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
};
NR_SRB_ToAddModList_t
*
SRBs
=
createSRBlist
(
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
,
dedicatedNAS_MessageList
,
cellGroupConfig
);
LOG_DUMPMSG
(
NR_RRC
,
DEBUG_RRC
,(
char
*
)
buffer
,
size
,
"[MSG] RRC Reconfiguration
\n
"
);
free_defaultMeasConfig
(
measconfig
);
LOG_DUMPMSG
(
NR_RRC
,
DEBUG_RRC
,
(
char
*
)
buffer
,
size
,
"[MSG] RRC Reconfiguration
\n
"
);
freeSRBlist
(
SRBs
);
freeDRBlist
(
DRBs
);
ASN_STRUCT_FREE
(
asn_DEF_NR_DRB_ToReleaseList
,
ue_p
->
DRB_ReleaseList
);
...
...
@@ -1166,14 +1194,9 @@ fallback_rrc_setup:
return
;
}
static
void
rrc_gNB_process_Measurement
Report
(
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
))
xer_fprint
(
stdout
,
&
asn_DEF_NR_MeasurementReport
,
(
void
*
)
measurementReport
);
DevAssert
(
measurementReport
->
criticalExtensions
.
present
==
NR_MeasurementReport__criticalExtensions_PR_measurementReport
&&
measurementReport
->
criticalExtensions
.
choice
.
measurementReport
!=
NULL
);
// LOG_I(NR_RRC, "Periodical Event Report! Do Nothing for now...\n");
gNB_RRC_UE_t
*
ue_ctxt
=
&
ue_context
->
ue_context
;
ASN_STRUCT_FREE
(
asn_DEF_NR_MeasResults
,
ue_ctxt
->
measResults
);
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
;
}
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
,
"
\n
HO LOG: Event A2 (Serving becomes worse than threshold)
\n
"
);
break
;
case
NR_EventTriggerConfig__eventId_PR_eventA3
:
{
LOG_I
(
NR_RRC
,
"
\n
HO 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
,
rrc_gNB_ue_context_t
*
ue_context_p
,
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_CellGroupConfig
,
UE
->
masterCellGroup
);
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
)
...
...
openair2/RRC/NR/rrc_gNB_du.c
View file @
7db4732c
...
...
@@ -27,7 +27,26 @@
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/F1AP/f1ap_ids.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
)
{
...
...
@@ -104,6 +123,80 @@ static NR_MeasurementTimingConfiguration_t *extract_mtc(uint8_t *buf, int buf_le
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
)
{
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
,
};
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
,
.
num_cells_to_activate
=
1
,
.
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
);
}
}
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
)
{
...
...
openair2/RRC/NR/rrc_gNB_du.h
View file @
7db4732c
...
...
@@ -32,6 +32,7 @@ struct f1ap_lost_connection_t;
struct
gNB_RRC_INST_s
;
struct
nr_rrc_du_container_t
;
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_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_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
);
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_ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment