Compare commits

...

34 Commits

Author SHA1 Message Date
arora
2bd0ce22a7 Adding 20MHz configuration file and correcting readme 2024-06-07 13:38:43 +02:00
sagar arora
dad9c796cb Correcting the frequency used by NR-UE
Signed-off-by: sagar arora <sagar.arora@openairinterface.org>
2024-04-02 11:59:40 +02:00
sagar arora
0c5fe22b79 removing extra slices from du configuration file
Signed-off-by: sagar arora <sagar.arora@openairinterface.org>
2024-03-25 16:53:51 +01:00
sagar arora
3d05d940a3 (ci): updating upf remote gateway when ipv6 is enabled
Signed-off-by: sagar arora <sagar.arora@openairinterface.org>
2024-03-22 23:37:19 +01:00
sagar arora
a76674be42 personal docker image for o1 telnet 2024-03-13 15:26:24 +01:00
sagar arora
f82476025c Docker compose for telnet o1
- Adding docker compose for testing telnet with rfsim DU
- Updating gNB dockerfile with telnet o1 module
- Removing slices from cucp configuration files will add them via command line
2024-03-13 12:39:38 +01:00
Robert Schmidt
5ba0f11ef3 F1AP: message encoders should no trigger GTP
The F1AP message encoders and decoders should do only that, encoding and
decoding messages. For the actual logic handling, including set up and
teardown of bearers, we should use the handlers.

In this commit, delete GTP tunnel handling from encoders/decoders. For
the CU, this happens already in the CU-UP/E1 handlers in
cucp_cuup_handler.c.  For the DU, add it in the handlers in
mac_rrc_dl_handler.c.
2024-02-14 14:50:33 +01:00
Robert Schmidt
48e1468039 RLF: avoid encoder problem, evict afer 5s 2024-02-14 14:50:33 +01:00
Robert Schmidt
20b62f34a3 Implement restart using gNB-DU configuratino update 2024-02-14 14:50:33 +01:00
Robert Schmidt
2413dc74bd O1 stats without RRC (everything available in DU) 2024-02-14 14:50:33 +01:00
Robert Schmidt
c03e77b458 F1AP code for gNB-DU configuration update 2024-02-14 14:50:33 +01:00
Robert Schmidt
0de72f9e1f Refactor setup_req 2024-02-14 14:50:33 +01:00
Robert Schmidt
3b265e6c5c Read slices in DU 2024-02-14 14:50:33 +01:00
Robert Schmidt
14dcc97a99 gNB-DU config update in DU 2024-02-14 14:50:33 +01:00
Robert Schmidt
ef11cac4c6 f1ap 2024-02-14 14:50:33 +01:00
Robert Schmidt
11dd6491ee gNB-DU config update msg def and handle in CU 2024-02-14 14:50:33 +01:00
Robert Schmidt
6282c26de2 Refactor TDD/FDD config reading into functions 2024-02-14 14:50:03 +01:00
Robert Schmidt
c493e7994c RRC stats: show DU info 2024-02-14 14:50:03 +01:00
Robert Schmidt
c5da7ac9ad clean up 2024-02-14 14:50:03 +01:00
Robert Schmidt
a08fa58ebd Add extract_sys_info(): refactor DU cell sys_info handling in own function 2024-02-14 14:50:03 +01:00
Robert Schmidt
aa58389ff0 Remove dead code 2024-02-14 14:50:03 +01:00
Robert Schmidt
910e842049 Remove misleading comment 2024-02-14 14:50:03 +01:00
Robert Schmidt
c6ef9c3baf Correct F1 criticality 2024-02-14 14:50:03 +01:00
Robert Schmidt
b264f4aebf Working configs for O1 scenario 2024-02-14 14:50:03 +01:00
Robert Schmidt
dd01c029d8 Add basic O1 telnet module to read cell parameters 2024-02-14 14:50:03 +01:00
Robert Schmidt
98cbf6c080 Basic start/stop of nr-softmodem 2024-02-14 09:58:23 +01:00
Robert Schmidt
e1640d89b4 Changes F1 unclear, but does not functionally change anything
- readF1setup
- Forward declaration F1?

maybe for compilation
2024-02-14 09:57:49 +01:00
Robert Schmidt
b5499e1412 Trigger F1 UE context release if no UE context in RRC 2024-02-14 09:57:49 +01:00
Robert Schmidt
2270cd4cfa RLF handled after SRB retx failure 2024-02-14 09:57:49 +01:00
Robert Schmidt
45546102d7 Logs: no duplex mode logs, not telnet client connected logs 2024-02-14 09:57:49 +01:00
Robert Schmidt
2da515e51c NR MAC: save total/used PRBs aggregate 2024-02-14 09:57:49 +01:00
Robert Schmidt
5881077e86 Msg4 RNTI not found: abort RA 2024-02-14 09:57:49 +01:00
Robert Schmidt
e44d68287e Store SST/SD in RRC 2024-02-14 09:57:49 +01:00
Robert Schmidt
965ed3e8d3 config module: check that memory is enough, allow more restarts 2024-02-14 09:57:49 +01:00
64 changed files with 4037 additions and 614 deletions

View File

@@ -0,0 +1,234 @@
Active_gNBs = ( "du-rfsim");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_DU_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
gNB_name = "du-rfsim";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
nr_cellid = 12345678L;
////////// Physical parameters:
min_rxtxtime = 6;
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3410.4 MHz => 301 REs from PointA 25 PRBs + 1 RE
absoluteFrequencySSB = 627360;
dl_frequencyBand = 78;
# this is 3410.4 - (51*12*30e-3/2) = 3401.22 MHz
dl_absoluteFrequencyPointA = 626748;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 51;
#initialDownlinkBWP
#genericParameters
# this is RBstart=0,L=50 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 13750;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 11; # this means shift of 14, so Coreset is in PRBs 1..48, SSB starts at PRB 15
initialDLBWPsearchSpaceZero = 0;
#pdsch-ConfigCommon
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 78;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 1;
ul_carrierBandwidth = 51;
pMax = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 13750;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 100;
#prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 15;
preambleReceivedTargetPower = -104;
#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 = 3;
#oneHalf (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
#ra_ContentionResolutionTimer
#(0..7) 8,16,24,32,40,48,56,64
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR
#1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
#
msg1_SubcarrierSpacing = 1,
# restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0,
msg3_DeltaPreamble = 1;
p0_NominalWithGrant =-96;
# pucch-ConfigCommon setup :
# pucchGroupHopping
# 0 = neither, 1= group hopping, 2=sequence hopping
pucchGroupHopping = 0;
hoppingId = 40;
p0_nominal = -96;
# 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 = 5;
nrofDownlinkSlots = 2;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -25;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "f1";
local_n_if_name = "eth0";
local_n_address = "192.168.71.171";
remote_n_address = "192.168.71.150";
local_n_portc = 500;
local_n_portd = 2153;
remote_n_portc = 501;
remote_n_portd = 2153;
pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 200;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 200;
pucch0_dtx_threshold = 150;
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"
}
log_config: {
global_log_level = "info";
hw_log_level = "info";
phy_log_level = "info";
mac_log_level = "info";
rlc_log_level = "info";
f1ap_log_level = "info";
};

View File

@@ -16,7 +16,7 @@ gNBs =
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }, { sst = 2 }, { sst = 3 }) });
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
nr_cellid = 12345678L;

View File

@@ -15,7 +15,7 @@ gNBs =
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }, { sst = 2 }, { sst = 3 } ) });
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
nr_cellid = 12345678L;

View File

@@ -0,0 +1,235 @@
Active_gNBs = ( "du-rfsim");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_DU_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
gNB_name = "du-rfsim";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
nr_cellid = 12345678L;
////////// Physical parameters:
min_rxtxtime = 6;
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3410.4 MHz => 301 REs from PointA 25 PRBs + 1 RE
absoluteFrequencySSB = 630048;
dl_frequencyBand = 78;
# this is 3410.4 - (51*12*30e-3/2) = 3401.22 MHz
dl_absoluteFrequencyPointA = 629436;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 51;
#initialDownlinkBWP
#genericParameters
# this is RBstart=0,L=50 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 13750;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialDLBWPsubcarrierSpacing = 1;
#pdcch-ConfigCommon
initialDLBWPcontrolResourceSetZero = 11; # this means shift of 14, so Coreset is in PRBs 1..48, SSB starts at PRB 15
initialDLBWPsearchSpaceZero = 0;
#pdsch-ConfigCommon
#uplinkConfigCommon
#frequencyInfoUL
ul_frequencyBand = 78;
#scs-SpecificCarrierList
ul_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
ul_subcarrierSpacing = 1;
ul_carrierBandwidth = 51;
pMax = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 13750;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
initialULBWPsubcarrierSpacing = 1;
#rach-ConfigCommon
#rach-ConfigGeneric
prach_ConfigurationIndex = 100;
#prach_msg1_FDM
#0 = one, 1=two, 2=four, 3=eight
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 15;
preambleReceivedTargetPower = -104;
#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 = 3;
#oneHalf (0..15) 4,8,12,16,...60,64
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
#ra_ContentionResolutionTimer
#(0..7) 8,16,24,32,40,48,56,64
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
#prach-RootSequenceIndex_PR
#1 = 839, 2 = 139
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
#
msg1_SubcarrierSpacing = 1,
# restrictedSetConfig
# 0=unrestricted, 1=restricted type A, 2=restricted type B
restrictedSetConfig = 0,
msg3_DeltaPreamble = 1;
p0_NominalWithGrant =-96;
# pucch-ConfigCommon setup :
# pucchGroupHopping
# 0 = neither, 1= group hopping, 2=sequence hopping
pucchGroupHopping = 0;
hoppingId = 40;
p0_nominal = -96;
# 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 = 5;
nrofDownlinkSlots = 2;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = -25;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "f1";
local_n_if_name = "eth0";
local_n_address = "192.168.71.171";
remote_n_address = "192.168.71.150";
local_n_portc = 500;
local_n_portd = 2153;
remote_n_portc = 501;
remote_n_portd = 2153;
pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 200;
}
);
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 200;
pucch0_dtx_threshold = 150;
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"
}
log_config: {
global_log_level = "info";
hw_log_level = "info";
phy_log_level = "info";
mac_log_level = "info";
rlc_log_level = "info";
f1ap_log_level = "info";
};

View File

@@ -1,4 +1,4 @@
Active_gNBs = ( "gNB-in-docker");
Active_gNBs = ( "gNB-DU-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
@@ -6,17 +6,32 @@ gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
gNB_name = "gNB-in-docker";
gNB_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
gNB_name = "gNB-DU-in-docker";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 222; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) });
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1 }) });
nr_cellid = 12345678L;
////////// Physical parameters:
#min_rxtxtime = 6;
force_256qam_off = 0;
do_CSIRS = 0;
do_SRS = 0;
pdcch_ConfigSIB1 = (
{
controlResourceSetZero = 12;
searchSpaceZero = 0;
}
);
servingCellConfigCommon = (
{
@@ -156,36 +171,35 @@ gNBs =
////////// AMF parameters:
amf_ip_address = ( { ipv4 = "172.21.16.137";
amf_ip_address = ( { ipv4 = "192.168.70.132";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_NG_AMF = "eth0";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.68.194";
GNB_INTERFACE_NAME_FOR_NGU = "eth0";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.68.194";
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp3s0";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "10.0.0.2";
GNB_INTERFACE_NAME_FOR_NGU = "enp3s0";
GNB_IPV4_ADDRESS_FOR_NGU = "10.0.0.2";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 200;
ul_prbblack_SNR_threshold = 10;
ulsch_max_frame_inactivity = 0;
}
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 230; # 200; after test in lab
pucch_TargetSNRx10 = 200;
ulsch_max_frame_inactivity = 1;
ul_max_mcs = 16;
min_grant_prb = 20;
}
);
L1s = (
@@ -203,11 +217,11 @@ RUs = (
local_rf = "yes"
nb_tx = 1
nb_rx = 1
att_tx = 14;
att_rx = 14;
att_tx = 6; # 8; after test in lab
att_rx = 6; # 8; after test in lab
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 114;
max_rxgain = 120;
eNB_instances = [0];
#beamforming 1x4 matrix:
bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000];
@@ -224,22 +238,6 @@ THREAD_STRUCT = (
}
);
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 :
{
@@ -250,6 +248,6 @@ log_config :
rlc_log_level ="info";
pdcp_log_level ="info";
rrc_log_level ="info";
ngap_log_level ="debug";
f1ap_log_level ="debug";
ngap_log_level ="info";
f1ap_log_level ="info";
};

View File

@@ -0,0 +1,386 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="../../../doc/images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">Testing O1 in containers</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
# 1. Deploy containers #
## 2.1. Deploy OAI 5G Core Network ##
```bash
docker-compose up -d mysql oai-amf oai-smf oai-upf oai-ext-dn
[+] Running 12/12
✔ Network rfsim5g-oai-core-net Created 0.1s
✔ Network rfsim5g-oai-traffic-net Created 0.1s
✔ Network rfsim5g-oai-e1-net Created 0.1s
✔ Network rfsim5g-oai-f1u-1-net Created 0.1s
✔ Network rfsim5g-oai-f1c-net Created 0.1s
✔ Network rfsim5g-oai-ue-net Created 0.1s
✔ Network rfsim5g-oai-o1-net Created 0.1s
✔ Container rfsim5g-mysql Started 0.3s
✔ Container rfsim5g-oai-amf Started 0.5s
✔ Container rfsim5g-oai-smf Started 0.7s
✔ Container rfsim5g-oai-upf Started 0.9s
✔ Container rfsim5g-oai-ext-dn Started 1.1s
```
```bash
docker-compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
rfsim5g-mysql mysql:8.0 "docker-entrypoint.s…" mysql About a minute ago Up About a minute (healthy) 3306/tcp, 33060/tcp
rfsim5g-oai-amf oaisoftwarealliance/oai-amf:v2.0.0 "/openair-amf/bin/oa…" oai-amf About a minute ago Up About a minute (healthy) 80/tcp, 9090/tcp, 38412/sctp
rfsim5g-oai-ext-dn oaisoftwarealliance/trf-gen-cn5g:focal "/bin/bash -c ' ipta…" oai-ext-dn About a minute ago Up About a minute (healthy)
rfsim5g-oai-smf oaisoftwarealliance/oai-smf:v2.0.0 "/openair-smf/bin/oa…" oai-smf About a minute ago Up About a minute (healthy) 80/tcp, 8080/tcp, 8805/udp
rfsim5g-oai-upf oaisoftwarealliance/oai-upf:v2.0.0 "/openair-upf/bin/oa…" oai-upf About a minute ago Up About a minute (healthy) 2152/udp, 8805/udp
```
## 2.2. Deploy OAI CU-CP, CU-UP and DU ##
```bash
docker-compose up -d oai-cu-cp oai-cu-up oai-du
[+] Running 7/7
✔ Container rfsim5g-mysql Running 0.0s
✔ Container rfsim5g-oai-amf Running 0.0s
✔ Container rfsim5g-oai-smf Running 0.0s
✔ Container rfsim5g-oai-upf Running 0.0s
✔ Container rfsim5g-oai-cucp Started 0.4s
✔ Container rfsim5g-oai-cuup Started 0.8s
✔ Container rfsim5g-oai-du Started 1.2s
```
## Check Stats via telnet O1 Module ##
Make sure you have installed `netcat` in your host machine or container.
In case you don't have then install in the gnb container
```bash
docker exec -it rfsim5g-oai-du bash
apt update -y && apt install netcat -y
```
```bash
echo o1 stats | nc -N 192.168.74.2 9090
```
<details>
<summary>The output is similar to:</summary>
```console
{
"o1-config": {
"BWP": {
"dl": [{
"bwp3gpp:isInitialBwp": true,
"bwp3gpp:numberOfRBs": 51,
"bwp3gpp:startRB": 0,
"bwp3gpp:subCarrierSpacing": 30
}],
"ul": [{
"bwp3gpp:isInitialBwp": true,
"bwp3gpp:numberOfRBs": 51,
"bwp3gpp:startRB": 0,
"bwp3gpp:subCarrierSpacing": 30
}]
},
"NRCELLDU": {
"nrcelldu3gpp:ssbFrequency": 630048,
"nrcelldu3gpp:arfcnDL": 629436,
"nrcelldu3gpp:bSChannelBwDL": 20,
"nrcelldu3gpp:arfcnUL": 629436,
"nrcelldu3gpp:bSChannelBwUL": 20,
"nrcelldu3gpp:nRPCI": 0,
"nrcelldu3gpp:nRTAC": 1,
"nrcelldu3gpp:mcc": "208",
"nrcelldu3gpp:mnc": "99",
"nrcelldu3gpp:sd": 16777215,
"nrcelldu3gpp:sst": 1
},
"device": {
"gnbId": 3584,
"gnbName": "du-rfsim",
"vendor": "OpenAirInterface"
}
},
"O1-Operational": {
"frame-type": "tdd",
"band-number": 78,
"num-ues": 0,
"ues": [ ],
"load": 0,
"ues-thp": [
]
}
}
```
</details>
Notice the block `O1-Operational` you will see the number of connected UEs, present load at the gNB and the DL/UL RLC `throughput` in `Kbps`.
## Deploy OAI NR-UE in RF simulator mode and in Standalone Mode ##
```bash
docker-compose up -d oai-nr-ue
[+] Running 8/8
✔ Container rfsim5g-mysql Running 0.0s
✔ Container rfsim5g-oai-amf Running 0.0s
✔ Container rfsim5g-oai-smf Running 0.0s
✔ Container rfsim5g-oai-upf Running 0.0s
✔ Container rfsim5g-oai-cucp Running 0.0s
✔ Container rfsim5g-oai-cuup Running 0.0s
✔ Container rfsim5g-oai-du Running 0.0s
✔ Container rfsim5g-oai-nr-ue Started 0.2s
```
Wait for a bit.
```bash
docker-compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
rfsim5g-mysql mysql:8.0 "docker-entrypoint.s…" mysql 30 minutes ago Up 30 minutes (healthy) 3306/tcp, 33060/tcp
rfsim5g-oai-amf oaisoftwarealliance/oai-amf:v2.0.0 "/openair-amf/bin/oa…" oai-amf 30 minutes ago Up 30 minutes (healthy) 80/tcp, 9090/tcp, 38412/sctp
rfsim5g-oai-cucp arorasagar/testing-images:oai-gnb-telnet "/opt/oai-gnb/bin/en…" oai-cu-cp 29 minutes ago Up 29 minutes (healthy)
rfsim5g-oai-cuup oaisoftwarealliance/oai-nr-cuup:v2.1.0 "/opt/oai-gnb/bin/en…" oai-cu-up 29 minutes ago Up 29 minutes (healthy)
rfsim5g-oai-du arorasagar/testing-images:oai-gnb-telnet "/opt/oai-gnb/bin/en…" oai-du 5 minutes ago Up 5 minutes (healthy)
rfsim5g-oai-ext-dn oaisoftwarealliance/trf-gen-cn5g:focal "/bin/bash -c ' ipta…" oai-ext-dn 30 minutes ago Up 30 minutes (healthy)
rfsim5g-oai-nr-ue oaisoftwarealliance/oai-nr-ue:v2.1.0 "/opt/oai-nr-ue/bin/…" oai-nr-ue 4 minutes ago Up 4 minutes (healthy)
rfsim5g-oai-smf oaisoftwarealliance/oai-smf:v2.0.0 "/openair-smf/bin/oa…" oai-smf 30 minutes ago Up 30 minutes (healthy) 80/tcp, 8080/tcp, 8805/udp
rfsim5g-oai-upf oaisoftwarealliance/oai-upf:v2.0.0 "/openair-upf/bin/oa…" oai-upf 30 minutes ago Up 30 minutes (healthy) 2152/udp, 8805/udp
```
Making sure the OAI UE is connected:
```bash
docker exec -it rfsim5g-oai-nr-ue ifconfig oaitun_ue1
oaitun_ue1: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 12.1.1.2 netmask 255.255.255.0 destination 12.1.1.2
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
```
Now if you will re-check the stats you will see
```bash
echo o1 stats | nc -N 192.168.74.2 9090
```
<details>
<summary>The output is similar to:</summary>
```console
{
"o1-config": {
"BWP": {
"dl": [{
"bwp3gpp:isInitialBwp": true,
"bwp3gpp:numberOfRBs": 51,
"bwp3gpp:startRB": 0,
"bwp3gpp:subCarrierSpacing": 30
}],
"ul": [{
"bwp3gpp:isInitialBwp": true,
"bwp3gpp:numberOfRBs": 51,
"bwp3gpp:startRB": 0,
"bwp3gpp:subCarrierSpacing": 30
}]
},
"NRCELLDU": {
"nrcelldu3gpp:ssbFrequency": 627360,
"nrcelldu3gpp:arfcnDL": 626748,
"nrcelldu3gpp:bSChannelBwDL": 20,
"nrcelldu3gpp:arfcnUL": 626748,
"nrcelldu3gpp:bSChannelBwUL": 20,
"nrcelldu3gpp:nRPCI": 0,
"nrcelldu3gpp:nRTAC": 1,
"nrcelldu3gpp:mcc": "208",
"nrcelldu3gpp:mnc": "99",
"nrcelldu3gpp:sd": 16777215,
"nrcelldu3gpp:sst": 1
},
"device": {
"gnbId": 3584,
"gnbName": "du-rfsim",
"vendor": "OpenAirInterface"
}
},
"O1-Operational": {
"frame-type": "tdd",
"band-number": 78,
"num-ues": 1,
"ues": [39874 ],
"load": 0,
"ues-thp": [
{"rnti": 39874, "dl": 0, "ul": 0}
]
}
}
```
</details>
You can do some throughput test and check load for this you need to install `iperf3` in the UE container
```bash
docker exec -it rfsim5g-oai-nr-ue bash
apt update -y && apt install iperf3 -y
exit
```
Iperf3 server is already running you can start Iperf3 client
```bash
docker exec -it rfsim5g-oai-nr-ue iperf3 -B 12.1.1.2 -b 80M -c 192.168.72.135 -R -t 100
```
Measure the load
```bash
echo o1 stats | nc -N 192.168.74.2 9090
```
<details>
<summary>The output is similar to:</summary>
```console
"O1-Operational": {
"frame-type": "tdd",
"band-number": 78,
"num-ues": 1,
"ues": [39874 ],
"load": 95,
"ues-thp": [
{"rnti": 39874, "dl": 52596, "ul": 913}
]
}
```
</details>
Now re-configure the bandwidth
1. Stop the L1
```bash
echo o1 stop_modem | nc -N 192.168.74.2 9090
```
2. Reconfigure bandwidth
```bash
echo o1 bwconfig 40 | nc -N 192.168.74.2 9090
```
3. Start L1
```bash
echo o1 start_modem | nc -N 192.168.74.2 9090
```
4. Check the reconfigured bandwidth
```bash
echo o1 stats | nc -N 192.168.74.2 9090
```
```bash
{
"o1-config": {
"BWP": {
"dl": [{
"bwp3gpp:isInitialBwp": true,
"bwp3gpp:numberOfRBs": 106,
"bwp3gpp:startRB": 0,
"bwp3gpp:subCarrierSpacing": 30
}],
"ul": [{
"bwp3gpp:isInitialBwp": true,
"bwp3gpp:numberOfRBs": 106,
"bwp3gpp:startRB": 0,
"bwp3gpp:subCarrierSpacing": 30
}]
},
"NRCELLDU": {
"nrcelldu3gpp:ssbFrequency": 641280,
"nrcelldu3gpp:arfcnDL": 640008,
"nrcelldu3gpp:bSChannelBwDL": 40,
"nrcelldu3gpp:arfcnUL": 640008,
"nrcelldu3gpp:bSChannelBwUL": 40,
"nrcelldu3gpp:nRPCI": 0,
"nrcelldu3gpp:nRTAC": 1,
"nrcelldu3gpp:mcc": "208",
"nrcelldu3gpp:mnc": "99",
"nrcelldu3gpp:sd": 16777215,
"nrcelldu3gpp:sst": 1
},
"device": {
"gnbId": 3584,
"gnbName": "du-rfsim",
"vendor": "OpenAirInterface"
}
},
"O1-Operational": {
"frame-type": "tdd",
"band-number": 78,
"num-ues": 0,
"ues": [ ],
"load": 14,
"ues-thp": [
]
}
}
```
You can see `nrcelldu3gpp:bSChannelBwUL` as 40.
5. Re-connect UE
In the [docker-compose.yaml](./docker-compose.yaml) file in `oai-nr-ue` section you need to change the UE command to 40MHz bandwidth.
```
# # 20 MHz
# USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time
# -r 51 --numerology 1 -C 3450720000 --ssb 186
# --uicc0.imsi 208990100001100
# --rfsimulator.serveraddr 192.168.78.2
# 40 MHz
USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time
-r 106 --numerology 1 -C 3619200000
--uicc0.imsi 208990100001100
--rfsimulator.serveraddr 192.168.78.2
```
```bash
docker rm rfsim5g-oai-nr-ue
docker-compose up -d oai-nr-ue
```
After this you can deploy the UE and again do an iperf3 test you will see the load is almost half now
```
"O1-Operational": {
"frame-type": "tdd",
"band-number": 78,
"num-ues": 1,
"ues": [25333 ],
"load": 52,
"ues-thp": [
{"rnti": 25333, "dl": 83266, "ul": 1123}
]
}
```

View File

@@ -0,0 +1,247 @@
services:
mysql:
container_name: "rfsim5g-mysql"
image: mysql:8.0
volumes:
- ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
- ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
environment:
- TZ=Europe/Paris
- MYSQL_DATABASE=oai_db
- MYSQL_USER=test
- MYSQL_PASSWORD=test
- MYSQL_ROOT_PASSWORD=linux
healthcheck:
test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
interval: 10s
timeout: 5s
retries: 30
networks:
core_net:
ipv4_address: 192.168.71.131
oai-amf:
container_name: "rfsim5g-oai-amf"
image: oaisoftwarealliance/oai-amf:v2.0.0
environment:
- TZ=Europe/paris
volumes:
- ./mini_nonrf_config.yaml:/openair-amf/etc/config.yaml
depends_on:
- mysql
networks:
core_net:
ipv4_address: 192.168.71.132
oai-smf:
container_name: "rfsim5g-oai-smf"
image: oaisoftwarealliance/oai-smf:v2.0.0
environment:
- TZ=Europe/Paris
volumes:
- ./mini_nonrf_config.yaml:/openair-smf/etc/config.yaml
depends_on:
- oai-amf
networks:
core_net:
ipv4_address: 192.168.71.133
oai-upf:
container_name: "rfsim5g-oai-upf"
image: oaisoftwarealliance/oai-upf:v2.0.0
environment:
- TZ=Europe/Paris
volumes:
- ./mini_nonrf_config.yaml:/openair-upf/etc/config.yaml
depends_on:
- oai-smf
cap_add:
- NET_ADMIN
- SYS_ADMIN
cap_drop:
- ALL
privileged: true
networks:
core_net:
ipv4_address: 192.168.71.134
traffic_net:
ipv4_address: 192.168.72.134
oai-ext-dn:
privileged: true
container_name: rfsim5g-oai-ext-dn
image: oaisoftwarealliance/trf-gen-cn5g:focal
entrypoint: /bin/bash -c \
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
"ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; iperf3 -s -D;sleep infinity"
depends_on:
- oai-upf
networks:
traffic_net:
ipv4_address: 192.168.72.135
healthcheck:
test: /bin/bash -c "ping -c 2 192.168.72.134"
interval: 10s
timeout: 5s
retries: 5
oai-cu-cp:
image: arorasagar/testing-images:oai-gnb-telnet
privileged: true
container_name: rfsim5g-oai-cucp
environment:
USE_ADDITIONAL_OPTIONS: --sa --log_config.global_log_options level,nocolor,time
--gNBs.[0].E1_INTERFACE.[0].ipv4_cucp 192.168.77.2
--gNBs.[0].local_s_address 192.168.72.2
ASAN_OPTIONS: detect_leaks=0
depends_on:
- oai-upf
networks:
core_net:
ipv4_address: 192.168.71.150
f1c_net:
ipv4_address: 192.168.72.2
e1_net:
ipv4_address: 192.168.77.2
volumes:
- ../../conf_files/gnb-cucp.sa.f1.conf:/opt/oai-gnb/etc/gnb.conf
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
interval: 10s
timeout: 5s
retries: 5
oai-cu-up:
image: oaisoftwarealliance/oai-nr-cuup:v2.1.0
privileged: true
container_name: rfsim5g-oai-cuup
environment:
USE_ADDITIONAL_OPTIONS: --sa --log_config.global_log_options level,nocolor,time
--gNBs.[0].E1_INTERFACE.[0].ipv4_cucp 192.168.77.2
--gNBs.[0].E1_INTERFACE.[0].ipv4_cuup 192.168.77.3
--gNBs.[0].local_s_address 192.168.73.2
--gNBs.[0].remote_s_address 127.0.0.1
ASAN_OPTIONS: detect_leaks=0
depends_on:
- oai-cu-cp
networks:
core_net:
ipv4_address: 192.168.71.161
f1u_net:
ipv4_address: 192.168.73.2
e1_net:
ipv4_address: 192.168.77.3
volumes:
- ../../conf_files/gnb-cuup.sa.f1.conf:/opt/oai-gnb/etc/gnb.conf
healthcheck:
test: /bin/bash -c "pgrep nr-cuup"
interval: 10s
timeout: 5s
retries: 5
oai-du:
image: arorasagar/testing-images:oai-gnb-telnet
privileged: true
container_name: rfsim5g-oai-du
environment:
USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time
--MACRLCs.[0].local_n_address 192.168.73.3
--MACRLCs.[0].remote_n_address 192.168.72.2
--telnetsrv --telnetsrv.shrmod o1 --telnetsrv.listenaddr 192.168.74.2
ASAN_OPTIONS: detect_leaks=0
depends_on:
- oai-cu-cp
- oai-cu-up
networks:
f1c_net:
ipv4_address: 192.168.72.3
f1u_net:
ipv4_address: 192.168.73.3
o1_net:
ipv4_address: 192.168.74.2
ue_net:
ipv4_address: 192.168.78.2
volumes:
- ../../conf_files/gnb-du.sa.band78.51prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf
healthcheck:
test: /bin/bash -c "pgrep nr-softmodem"
interval: 10s
timeout: 5s
retries: 5
oai-nr-ue:
image: oaisoftwarealliance/oai-nr-ue:v2.1.0
privileged: true
container_name: rfsim5g-oai-nr-ue
environment:
# # 20 MHz
# USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time
# -r 51 --numerology 1 -C 3450720000 --ssb 186
# --uicc0.imsi 208990100001100
# --rfsimulator.serveraddr 192.168.78.2
# 40 MHz
USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time
-r 106 --numerology 1 -C 3619200000
--uicc0.imsi 208990100001100
--rfsimulator.serveraddr 192.168.78.2
depends_on:
- oai-du
networks:
ue_net:
ipv4_address: 192.168.78.5
volumes:
- ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf
healthcheck:
test: /bin/bash -c "pgrep nr-uesoftmodem"
interval: 10s
timeout: 5s
retries: 5
networks:
core_net:
driver: bridge
name: rfsim5g-oai-core-net
ipam:
config:
- subnet: 192.168.71.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-core"
traffic_net:
driver: bridge
name: rfsim5g-oai-traffic-net
ipam:
config:
- subnet: 192.168.72.128/26
driver_opts:
com.docker.network.bridge.name: "rfsim5g-traffic"
f1c_net:
driver: bridge
name: rfsim5g-oai-f1c-net
ipam:
config:
- subnet: 192.168.72.0/28
driver_opts:
com.docker.network.bridge.name: "rfsim5g-f1c"
f1u_net:
driver: bridge
name: rfsim5g-oai-f1u-1-net
ipam:
config:
- subnet: 192.168.73.0/28
driver_opts:
com.docker.network.bridge.name: "rfsim5g-f1u"
o1_net:
driver: bridge
name: rfsim5g-oai-o1-net
ipam:
config:
- subnet: 192.168.74.0/28
driver_opts:
com.docker.network.bridge.name: "rfsim5g-o1"
e1_net:
driver: bridge
name: rfsim5g-oai-e1-net
ipam:
config:
- subnet: 192.168.77.0/28
driver_opts:
com.docker.network.bridge.name: "rfsim5g-e1"
ue_net:
driver: bridge
name: rfsim5g-oai-ue-net
ipam:
config:
- subnet: 192.168.78.0/28
driver_opts:
com.docker.network.bridge.name: "rfsim5g-ue"

View File

@@ -0,0 +1,189 @@
################################################################################
# Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The OpenAirInterface Software Alliance licenses this file to You under
# the OAI Public License, Version 1.1 (the "License"); you may not use this file
# except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.openairinterface.org/?page_id=698
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
# For more information about the OpenAirInterface (OAI) Software Alliance:
# contact@openairinterface.org
################################################################################
# OAI CN Configuration File
### This file can be used by all OAI NFs
### Some fields are specific to an NF and will be ignored by other NFs
## NOTE ON YAML ANCHORS ##
# We use YAML anchors to ease the configuration and to avoid duplicating parts of the configuration.
# This is especially true for the SNSSAIs, as we have to define them for multiple NFs.
# Please note that the use of anchors is not mandatory, and you can define the SNSSAI in each NF yourself.
# You can read more about anchors here: https://yaml.org/spec/1.2.2/#anchors-and-aliases
############# Common configuration
# Log level for all the NFs
log_level:
general: debug
# If you enable registration, the other NFs will use the NRF discovery mechanism
register_nf:
general: no
http_version: 1
############## SBI Interfaces
### Each NF takes its local SBI interfaces and remote interfaces from here, unless it gets them using NRF discovery mechanisms
nfs:
amf:
host: oai-amf
sbi:
port: 80
api_version: v1
interface_name: eth0
n2:
interface_name: eth0
port: 38412
smf:
host: oai-smf
sbi:
port: 80
api_version: v1
interface_name: eth0
n4:
interface_name: eth0
port: 8805
upf:
host: oai-upf
sbi:
port: 80
api_version: v1
interface_name: eth0
n3:
interface_name: eth0
port: 2152
n4:
interface_name: eth0
port: 8805
n6:
interface_name: eth1
n9:
interface_name: eth0
port: 2152
#### Common for UDR and AMF
database:
host: mysql
user: test
type: mysql
password: test
database_name: oai_db
generate_random: true
connection_timeout: 300 # seconds
## general single_nssai configuration
## Defines YAML anchors, which are reused in the config file
snssais:
- &embb_slice1
sst: 1
############## NF-specific configuration
amf:
amf_name: "OAI-AMF"
# This really depends on if we want to keep the "mini" version or not
support_features_options:
enable_simple_scenario: yes # "no" by default with the normal deployment scenarios with AMF/SMF/UPF/AUSF/UDM/UDR/NRF.
# set it to "yes" to use with the minimalist deployment scenario (including only AMF/SMF/UPF) by using the internal AUSF/UDM implemented inside AMF.
# There's no NRF in this scenario, SMF info is taken from "nfs" section.
enable_nssf: no
enable_smf_selection: no
relative_capacity: 30
statistics_timer_interval: 20 # in seconds
emergency_support: false
served_guami_list:
- mcc: 208
mnc: 99
amf_region_id: 01
amf_set_id: 001
amf_pointer: 01
plmn_support_list:
- mcc: 208
mnc: 99
tac: 0x0001
nssai:
- *embb_slice1
supported_integrity_algorithms:
- "NIA0"
- "NIA1"
- "NIA2"
supported_encryption_algorithms:
- "NEA0"
- "NEA1"
- "NEA2"
smf:
ue_mtu: 1500
support_features:
use_local_subscription_info: yes # Use infos from local_subscription_info or from UDM
use_local_pcc_rules: yes # Use infos from local_pcc_rules or from PCF
upfs:
- host: oai-upf
port: 8805
config:
enable_usage_reporting: no
# follows UPFInfo from 3GPP TS 29.510, currently only these values from interfaceUpfInfoList are supported
upf_info:
interfaceUpfInfoList:
- interfaceType: "N3"
networkInstance: "access.oai.org"
- interfaceType: "N6"
networkInstance: "core.oai.org"
ue_dns:
primary_ipv4: "172.21.3.100"
primary_ipv6: "2001:4860:4860::8888"
secondary_ipv4: "8.8.8.8"
secondary_ipv6: "2001:4860:4860::8888"
ims:
pcscf_ipv4: "127.0.0.1"
pcscf_ipv6: "fe80::7915:f408:1787:db8b"
# the DNN you configure here should be configured in "dnns"
# follows the SmfInfo datatype from 3GPP TS 29.510
smf_info:
sNssaiSmfInfoList:
- sNssai: *embb_slice1
dnnSmfInfoList:
- dnn: "oai"
local_subscription_infos:
- single_nssai: *embb_slice1
dnn: "oai"
qos_profile:
5qi: 9
session_ambr_ul: "200Mbps"
session_ambr_dl: "400Mbps"
upf:
support_features:
enable_bpf_datapath: no # If "on": BPF is used as datapath else simpleswitch is used, DEFAULT= off
enable_snat: yes # If "on": Source natting is done for UE, DEFAULT= off
remote_n6_gw: 127.0.0.1 # Dummy host since simple-switch does not use N6 GW
upf_info:
sNssaiUpfInfoList:
- sNssai: *embb_slice1
dnnUpfInfoList:
- dnn: "oai"
## DNN configuration
dnns:
- dnn: "oai"
pdu_session_type: "IPV4"
ipv4_subnet: "12.1.1.0/24"

View File

@@ -0,0 +1,46 @@
#!/bin/bash
set -eo pipefail
if [ "$MYSQL_ROOT_PASSWORD" ] && [ -z "$MYSQL_USER" ] && [ -z "$MYSQL_PASSWORD" ]; then
echo >&2 'Healthcheck error: cannot determine root password (and MYSQL_USER and MYSQL_PASSWORD were not set)'
exit 0
fi
host="$(hostname --ip-address || echo '127.0.0.1')"
user="${MYSQL_USER:-root}"
export MYSQL_PWD="${MYSQL_PASSWORD:-$MYSQL_ROOT_PASSWORD}"
args=(
# force mysql to not use the local "mysqld.sock" (test "external" connectivity)
-h"$host"
-u"$user"
--silent
)
STATUS=0
if command -v mysqladmin &> /dev/null; then
if mysqladmin "${args[@]}" ping > /dev/null; then
database_check=$(mysql -u$user -D oai_db --silent -e "SELECT * FROM users;")
if [[ -z $database_check ]]; then
echo "Healthcheck error: oai_db not populated"
STATUS=1
fi
STATUS=0
else
echo "Healthcheck error: Mysql port inactive"
STATUS=1
fi
else
if select="$(echo 'SELECT 1' | mysql "${args[@]}")" && [ "$select" = '1' ]; then
database_check=$(mysql -u$user -D oai_db --silent -e "SELECT * FROM users;")
if [[ -z $database_check ]]; then
echo "Healthcheck error: oai_db not populated"
STATUS=1
fi
STATUS=0
else
echo "Healthcheck error: Mysql port inactive"
STATUS=1
fi
fi
exit $STATUS

File diff suppressed because one or more lines are too long

View File

@@ -112,6 +112,7 @@ void *config_allocate_new(configmodule_interface_t *cfg, int sz, bool autoFree)
// add the memory piece in the managed memory pieces list
pthread_mutex_lock(&cfg->memBlocks_mutex);
int newBlockIdx=cfg->numptrs++;
AssertFatal(newBlockIdx <= sizeof(cfg->oneBlock) / sizeof(cfg->oneBlock[0]), "reached maximum number of dynamically allocatable blocks\n");
oneBlock_t* tmp=&cfg->oneBlock[newBlockIdx];
tmp->ptrs = (char *)ptr;
tmp->ptrsAllocated = true;

View File

@@ -41,7 +41,7 @@
#include "common/config/config_paramdesc.h"
#include "common/utils/T/T.h"
#define CONFIG_MAX_OOPT_PARAMS 10 // maximum number of parameters in the -O option (-O <cfgmode>:P1:P2...
#define CONFIG_MAX_ALLOCATEDPTRS 2048 // maximum number of parameters that can be dynamicaly allocated in the config module
#define CONFIG_MAX_ALLOCATEDPTRS 32768 // maximum number of parameters that can be dynamicaly allocated in the config module
/* default values for configuration module parameters */
#define CONFIG_LIBCONFIGFILE "libconfig" // use libconfig file

View File

@@ -411,7 +411,7 @@ frame_type_t get_frame_type(uint16_t current_band, uint8_t scs_index)
else
current_type = FDD;
LOG_I(NR_MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex);
LOG_D(NR_MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex);
return current_type;
}
@@ -423,7 +423,7 @@ int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index)
int32_t delta_duplex = (nr_bandtable[nr_table_idx].ul_min - nr_bandtable[nr_table_idx].dl_min);
LOG_I(NR_MAC, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band);
LOG_D(NR_MAC, "NR band duplex spacing is %d KHz (nr_bandtable[%d].band = %d)\n", delta_duplex, nr_table_idx, nr_bandtable[nr_table_idx].band);
return delta_duplex;
}

View File

@@ -64,8 +64,14 @@ add_library(telnetsrv_bearer MODULE telnetsrv_bearer.c)
target_link_libraries(telnetsrv_bearer PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies(telnetsrv telnetsrv_bearer)
message(STATUS "Add CI specific telnet functions in libtelnetsrv_o1.so")
add_library(telnetsrv_o1 MODULE telnetsrv_o1.c)
target_link_libraries(telnetsrv_o1 PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_dependencies(telnetsrv telnetsrv_o1)
# all libraries should be written to root build dir
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_bearer
telnetsrv_o1
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..
)

View File

@@ -0,0 +1,185 @@
[[_TOC_]]
The telnet O1 module (`telnetsrv_o1.c`) can be used to perform some O1-related
actions (reading data, starting and stopping the nr-softmodem, reconfigurating
frequency and bandwidth).
# General usage
The usage is similar to the general telnet usage, but in short:
```
./build_oai --ninja -c --gNB --nrUE --build-lib telnetsrv
```
to build everything including the telnet library. Then, run the nr-softmodem
by activating telnet and loading the `o1` module:
```
./nr-softmodem -O <config> --telnetsrv --telnetsrv.shrmod o1
```
Afterwards, it should be possible to connect via telnet on localhost, port
9090. Use `help` to get help on the different command sections, and type e.g.
`o1 stats` to get statistics (more information further below):
```
$ telnet 127.0.0.1 9090
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
softmodem_gnb> help
[...]
module 4 = o1:
o1 stats
o1 config ?
o1 stop_modem
o1 start_modem
[...]
softmodem_gnb> o1 stats
[...]
softmodem_gnb> exit
Connection closed by foreign host.
```
It also possible to send a command "directly from the command line", by piping
the command into netcat:
```
echo o1 stats | nc -N 127.0.0.1 9090
```
Note that only one telnet client can be connected at a time.
# Get statistics
Use the `o1 stats` command. The output is in JSON format:
```json
{
"o1-config": {
"BWP": {
"dl": [
{
"bwp3gpp:isInitialBwp": true,
"bwp3gpp:numberOfRBs": 106,
"bwp3gpp:startRB": 0,
"bwp3gpp:subCarrierSpacing": 30
}
],
"ul": [
{
"bwp3gpp:isInitialBwp": true,
"bwp3gpp:numberOfRBs": 106,
"bwp3gpp:startRB": 0,
"bwp3gpp:subCarrierSpacing": 30
}
]
},
"NRCELLDU": {
"nrcelldu3gpp:ssbFrequency": 641280,
"nrcelldu3gpp:arfcnDL": 640008,
"nrcelldu3gpp:bSChannelBwDL": 40,
"nrcelldu3gpp:arfcnUL": 640008,
"nrcelldu3gpp:bSChannelBwUL": 40,
"nrcelldu3gpp:nRPCI": 0,
"nrcelldu3gpp:nRTAC": 1,
"nrcelldu3gpp:mcc": "208",
"nrcelldu3gpp:mnc": "95",
"nrcelldu3gpp:sd": 16777215,
"nrcelldu3gpp:sst": 1
},
"device": {
"gnbId": 1,
"gnbName": "gNB-Eurecom-5GNRBox",
"vendor": "OpenAirInterface"
}
},
"O1-Operational": {
"frame-type": "tdd",
"band-number": 78,
"num-ues": 1,
"ues": [
6876
],
"load": 9,
"ues-thp": [
{
"rnti": 6876,
"dl": 3279,
"ul": 2725
}
]
}
}
```
Note that no actual JSON engine is used, so no actual verification is done; it
is for convenience of the consumer. To verify, you can employ `jq`:
```
echo o1 stats | nc -N 127.0.0.1 9090 | awk '/^{$/, /^}$/' | jq .
```
(`awk`'s pattern matching makes that only everything between the first `{` and
its corresponding `}` is printed).
There are two sections:
1. `.o1-config` show some stats that map directly to the O1 Netconf model. Note
that only one MCC/MNC/SD/SST (each) are supported right now. Also, note that
as per 3GPP specifications, SD of value `0xffffff` (16777215 in decimal)
means "no SD". `bSChannelBwDL/UL` is reported in MHz.
2. `.O1-operational` output some statistics that do not map yet to any netconf
parameters, but that might be useful nevertheless for a consumer.
# Write a new configuration
Use `o1 config` to write a configuration:
```
echo o1 config nrcelldu3gpp:ssbFrequency 620736 nrcelldu3gpp:arfcnDL 620020 nrcelldu3gpp:bSChannelBwDL 51 bwp3gpp:numberOfRBs 51 bwp3gpp:startRB 0 | nc -N 127.0.0.1 9090
```
You have to pass the above parameters in exactly this order. The softmodem
needs to be stopped; it will pick up the new configuration when starting the
softmodem again.
Note that you cannot switch three-quarter sampling for this as of now.
For values of the configuration, refer to the next section.
# Use hardcoded configuration
Use `o1 bwconfig` to write a hard-coded configuration for 20 or 40 MHz cells:
```
echo o1 bwconfig 20 | nc -N 127.0.0.1 9090
echo o1 bwconfig 40 | nc -N 127.0.0.1 9090
```
The softmodem needs to be stopped; it will pick up the new configuration when
starting the softmodem again.
Use `o1 stats` to see which configurations are set by these commands for the
parameters `nrcelldu3gpp:ssbFrequency`, `nrcelldu3gpp:arfcnDL`,
`nrcelldu3gpp:arfcnUL`, `nrcelldu3gpp:bSChannelBwDL`,
`nrcelldu3gpp:bSChannelBwUL`, and `bwp3gpp:numberOfRBsbwp3gpp:startRB`.
Furthermore, for 20MHz, it *disables* three-quarter sampling, whereas it
*enables* three-quarter sampling for 40MHz.
# Restart the softmodem
Use `o1 stop_modem` to stop the `nr-softmodem`. To restart the softmodem, use
`o1 start_modem`:
```
echo o1 stop_modem | nc -N 127.0.0.1 9090
echo o1 start_modem | nc -N 127.0.0.1 9090
```
In fact, stopping terminates all L1 threads and, due to implementation details,
the RRC thread. It will be as if the softmodem "freezes", and no periodical
output of statistics will occur (the O1 telnet interface will still work,
though). Starting again will "defreeze" the softmodem.
`stop_modem` works reliably at this point. `start_modem` comes with a couple of
caveats:
* not all memory is freed properly: for instance, the configuration module runs
out of memory after a couple of restarts, and will stop everything.
* it is advisable to disconnect any UE before stopping. The MAC runs in the
same thread as the L1, and since we stop the L1, it is as if the MAC
"freezes" in time. When you restart the softmodem, frame and slot numbers
might not match with data stored internally at the MAC, and the softmodem
might assert. Alse, any UE will be disconnected (USRP: no radio, RFsimulator:
TCP socket closed); this in itself is not a problem from a gNB perspective,
but of course the UE is not immediately operational after restarting.

View File

@@ -3,5 +3,6 @@ The oai embedded telnet server is an optional monitoring and debugging tool. It
* [Using the telnet server](telnetusage.md)
* [Adding commands to the oai telnet server](telnetaddcmd.md)
* [telnet server architecture ](telnetarch.md)
* [on the telnet O1 module](telneto1.md)
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)

View File

@@ -681,7 +681,6 @@ void run_telnetsrv(void) {
}
if(!readc) {
printf ("[TELNETSRV] Telnet Client disconnected.\n");
break;
}
@@ -727,7 +726,7 @@ void run_telnetsrv(void) {
write_history(telnetparams.histfile);
clear_history();
close(telnetparams.new_socket);
printf ("[TELNETSRV] Telnet server waitting for connection...\n");
//printf ("[TELNETSRV] Telnet server waitting for connection...\n");
}
close(sock);

View File

@@ -0,0 +1,447 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define TELNETSERVERCODE
#include "telnetsrv.h"
#include "openair2/RRC/NR/nr_rrc_defs.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "openair2/RRC/NR/nr_rrc_config.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c"
#include "common/utils/nr/nr_common.h"
#define ERROR_MSG_RET(mSG, aRGS...) do { prnt("FAILURE: " mSG, ##aRGS); return 1; } while (0)
#define ISINITBWP "bwp3gpp:isInitialBwp"
//#define CYCLPREF "bwp3gpp:cyclicPrefix"
#define NUMRBS "bwp3gpp:numberOfRBs"
#define STARTRB "bwp3gpp:startRB"
#define BWPSCS "bwp3gpp:subCarrierSpacing"
#define SSBFREQ "nrcelldu3gpp:ssbFrequency"
#define ARFCNDL "nrcelldu3gpp:arfcnDL"
#define BWDL "nrcelldu3gpp:bSChannelBwDL"
#define ARFCNUL "nrcelldu3gpp:arfcnUL"
#define BWUL "nrcelldu3gpp:bSChannelBwUL"
#define PCI "nrcelldu3gpp:nRPCI"
#define TAC "nrcelldu3gpp:nRTAC"
#define MCC "nrcelldu3gpp:mcc"
#define MNC "nrcelldu3gpp:mnc"
#define SD "nrcelldu3gpp:sd"
#define SST "nrcelldu3gpp:sst"
typedef struct b {
long int dl;
long int ul;
} b_t;
static int get_stats(char *buf, int debug, telnet_printfunc_t prnt)
{
if (buf)
ERROR_MSG_RET("no parameter allowed\n");
const gNB_MAC_INST *mac = RC.nrmac[0];
AssertFatal(mac != NULL, "need MAC\n");
const f1ap_setup_req_t *sr = mac->f1_config.setup_req;
const f1ap_served_cell_info_t *cell_info = &sr->cell[0].info;
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
const NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
const NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL;
frame_type_t frame_type = get_frame_type(*frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
const NR_BWP_t *initialUL = &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
int scs = initialDL->subcarrierSpacing;
AssertFatal(scs == initialUL->subcarrierSpacing, "different SCS for UL/DL not supported!\n");
int band = *frequencyInfoDL->frequencyBandList.list.array[0];
int nrb = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
AssertFatal(nrb == frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth, "different BW for UL/DL not supported!\n");
int bw_index = get_supported_band_index(scs, band, nrb);
int bw_mhz = get_supported_bw_mhz(band > 256 ? FR2 : FR1, bw_index);
int num_ues = 0;
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
num_ues++;
}
const mac_stats_t *stat = &mac->mac_stats;
static mac_stats_t last = {0};
int diff_used = stat->used_prb_aggregate - last.used_prb_aggregate;
int diff_total = stat->total_prb_aggregate - last.total_prb_aggregate;
int load = diff_total > 0 ? 100 * diff_used / diff_total : 0;
last = *stat;
static struct timespec tp_last = {0};
struct timespec tp_now;
clock_gettime(CLOCK_MONOTONIC, &tp_now);
size_t diff_msec = (tp_now.tv_sec - tp_last.tv_sec) * 1000 + (tp_now.tv_nsec - tp_last.tv_nsec) / 1000000;
tp_last = tp_now;
const int srb_flag = 0;
const int rb_id = 1;
static b_t last_total[MAX_MOBILES_PER_GNB] = {0};
b_t thr[MAX_MOBILES_PER_GNB] = {0};
int i = 0;
{
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
nr_rlc_statistics_t rlc = {0};
nr_rlc_get_statistics(it->rnti, srb_flag, rb_id, &rlc);
// static var last_total: we might have old data, larger than what
// reports RLC, leading to a huge number -> cut off to zero
if (last_total[i].dl > rlc.txpdu_bytes)
last_total[i].dl = rlc.txpdu_bytes;
if (last_total[i].ul > rlc.rxpdu_bytes)
last_total[i].ul = rlc.rxpdu_bytes;
thr[i].dl = (rlc.txpdu_bytes - last_total[i].dl) * 8 / diff_msec;
thr[i].ul = (rlc.rxpdu_bytes - last_total[i].ul) * 8 / diff_msec;
last_total[i].dl = rlc.txpdu_bytes;
last_total[i].ul = rlc.rxpdu_bytes;
i++;
}
}
prnt("{\n");
prnt(" \"o1-config\": {\n");
prnt(" \"BWP\": {\n");
prnt(" \"dl\": [{\n");
prnt(" \"" ISINITBWP "\": true,\n");
//prnt(" \"" CYCLPREF "\": %ld,\n", *initialDL->cyclicPrefix);
prnt(" \"" NUMRBS "\": %ld,\n", NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE));
prnt(" \"" STARTRB "\": %ld,\n", NRRIV2PRBOFFSET(initialDL->locationAndBandwidth, MAX_BWP_SIZE));
prnt(" \"" BWPSCS "\": %ld\n", 15 * (1U << scs));
prnt(" }],\n");
prnt(" \"ul\": [{\n");
prnt(" \"" ISINITBWP "\": true,\n");
//prnt(" \"" CYCLPREF "\": %ld,\n", *initialUL->cyclicPrefix);
prnt(" \"" NUMRBS "\": %ld,\n", NRRIV2BW(initialUL->locationAndBandwidth, MAX_BWP_SIZE));
prnt(" \"" STARTRB "\": %ld,\n", NRRIV2PRBOFFSET(initialUL->locationAndBandwidth, MAX_BWP_SIZE));
prnt(" \"" BWPSCS "\": %ld\n", 15 * (1U << scs));
prnt(" }]\n");
prnt(" },\n");
prnt(" \"NRCELLDU\": {\n");
prnt(" \"" SSBFREQ "\": %ld,\n", *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB);
prnt(" \"" ARFCNDL "\": %ld,\n", frequencyInfoDL->absoluteFrequencyPointA);
prnt(" \"" BWDL "\": %ld,\n", bw_mhz);
prnt(" \"" ARFCNUL "\": %ld,\n", frequencyInfoUL->absoluteFrequencyPointA ? *frequencyInfoUL->absoluteFrequencyPointA : frequencyInfoDL->absoluteFrequencyPointA);
prnt(" \"" BWUL "\": %ld,\n", bw_mhz);
prnt(" \"" PCI "\": %ld,\n", *scc->physCellId);
prnt(" \"" TAC "\": %ld,\n", *cell_info->tac);
prnt(" \"" MCC "\": \"%03d\",\n", cell_info->plmn.mcc);
prnt(" \"" MNC "\": \"%0*d\",\n", cell_info->plmn.mnc_digit_length, cell_info->plmn.mnc);
prnt(" \"" SD "\": %d,\n", cell_info->sd);
prnt(" \"" SST "\": %d\n", cell_info->sst);
prnt(" },\n");
prnt(" \"device\": {\n");
prnt(" \"gnbId\": %d,\n", sr->gNB_DU_id);
prnt(" \"gnbName\": \"%s\",\n", sr->gNB_DU_name);
prnt(" \"vendor\": \"OpenAirInterface\"\n");
prnt(" }\n");
prnt(" },\n");
prnt(" \"O1-Operational\": {\n");
prnt(" \"frame-type\": \"%s\",\n", frame_type == TDD ? "tdd" : "fdd");
prnt(" \"band-number\": %ld,\n", band);
prnt(" \"num-ues\": %d,\n", num_ues);
prnt(" \"ues\": [");
{
bool first = true;
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
if (!first) { prnt(", "); }
prnt("%d", it->rnti);
first = false;
}
}
prnt(" ],\n");
prnt(" \"load\": %d,\n", load);
prnt(" \"ues-thp\": [\n");
{
bool first = true;
int i = 0;
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
if (!first) { prnt(", "); }
prnt(" {\"rnti\": %d, \"dl\": %ld, \"ul\": %ld}\n", it->rnti, thr[i].dl, thr[i].ul);
i++;
first = false;
}
}
prnt(" ]\n");
prnt(" }\n");
prnt("}\n");
prnt("OK\n");
return 0;
}
static int read_long(const char *buf, const char *end, const char *id, long *val)
{
const char *curr = buf;
while (isspace(*curr) && curr < end) // skip leading spaces
curr++;
int len = strlen(id);
if (curr + len >= end)
return -1;
if (strncmp(curr, id, len) != 0) // check buf has id
return -1;
curr += len;
while (isspace(*curr) && curr < end) // skip middle spaces
curr++;
if (curr >= end)
return -1;
int nread = sscanf(curr, "%ld", val);
if (nread != 1)
return -1;
while (isdigit(*curr) && curr < end) // skip all digits read above
curr++;
if (curr > end)
return -1;
return curr - buf;
}
bool running = true; // in the beginning, the softmodem is started automatically
static int set_config(char *buf, int debug, telnet_printfunc_t prnt)
{
if (!buf)
ERROR_MSG_RET("need param: o1 config param1 val1 [param2 val2 ...]\n");
if (running)
ERROR_MSG_RET("cannot set parameters while L1 is running\n");
const char *end = buf + strlen(buf);
/* we need to update the following fields to change frequency and/or
* bandwidth:
* --gNBs.[0].servingCellConfigCommon.[0].absoluteFrequencySSB 620736 -> SSBFREQ
* --gNBs.[0].servingCellConfigCommon.[0].dl_absoluteFrequencyPointA 620020 -> ARFCNDL
* --gNBs.[0].servingCellConfigCommon.[0].dl_carrierBandwidth 51 -> BWDL
* --gNBs.[0].servingCellConfigCommon.[0].initialDLBWPlocationAndBandwidth 13750 -> NUMRBS + STARTRB
* --gNBs.[0].servingCellConfigCommon.[0].ul_carrierBandwidth 51 -> BWUL?
* --gNBs.[0].servingCellConfigCommon.[0].initialULBWPlocationAndBandwidth 13750 -> ?
*/
int processed = 0;
int pos = 0;
long ssbfreq;
processed = read_long(buf + pos, end, SSBFREQ, &ssbfreq);
if (processed < 0)
ERROR_MSG_RET("could not read " SSBFREQ " at index %d\n", pos + processed);
pos += processed;
prnt("setting " SSBFREQ ": %ld [len %d]\n", ssbfreq, pos);
long arfcn;
processed = read_long(buf + pos, end, ARFCNDL, &arfcn);
if (processed < 0)
ERROR_MSG_RET("could not read " ARFCNDL " at index %d\n", pos + processed);
pos += processed;
prnt("setting " ARFCNDL ": %ld [len %d]\n", arfcn, pos);
long bwdl;
processed = read_long(buf + pos, end, BWDL, &bwdl);
if (processed < 0)
ERROR_MSG_RET("could not read " BWDL " at index %d\n", pos + processed);
pos += processed;
prnt("setting " BWDL ": %ld [len %d]\n", bwdl, pos);
long numrbs;
processed = read_long(buf + pos, end, NUMRBS, &numrbs);
if (processed < 0)
ERROR_MSG_RET("could not read " NUMRBS " at index %d\n", pos + processed);
pos += processed;
prnt("setting " NUMRBS ": %ld [len %d]\n", numrbs, pos);
long startrb;
processed = read_long(buf + pos, end, STARTRB, &startrb);
if (processed < 0)
ERROR_MSG_RET("could not read " STARTRB " at index %d\n", pos + processed);
pos += processed;
prnt("setting " STARTRB ": %ld [len %d]\n", startrb, pos);
int locationAndBandwidth = PRBalloc_to_locationandbandwidth0(numrbs, startrb, MAX_BWP_SIZE);
prnt("inferred locationAndBandwidth: %d\n", locationAndBandwidth);
/*
gNB_RRC_INST *rrc = RC.nrrrc[0];
NR_ServingCellConfigCommon_t *scc = rrc->carrier.servingcellconfigcommon;
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL;
NR_BWP_t *initialUL = &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
//--gNBs.[0].servingCellConfigCommon.[0].absoluteFrequencySSB 620736 -> SSBFREQ
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB = ssbfreq;
// --gNBs.[0].servingCellConfigCommon.[0].dl_absoluteFrequencyPointA 620020 -> ARFCNDL
frequencyInfoDL->absoluteFrequencyPointA = arfcn;
AssertFatal(frequencyInfoUL->absoluteFrequencyPointA == NULL, "only handle TDD\n");
// --gNBs.[0].servingCellConfigCommon.[0].dl_carrierBandwidth 51 -> BWDL
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = bwdl;
// --gNBs.[0].servingCellConfigCommon.[0].initialDLBWPlocationAndBandwidth 13750 -> NUMRBS + STARTRB
initialDL->locationAndBandwidth = locationAndBandwidth;
// --gNBs.[0].servingCellConfigCommon.[0].ul_carrierBandwidth 51 -> BWUL?
// we assume the same BW as DL
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = bwdl;
// --gNBs.[0].servingCellConfigCommon.[0].initialULBWPlocationAndBandwidth 13750 -> ?
// we assume same locationAndBandwidth as DL
initialUL->locationAndBandwidth = locationAndBandwidth;
*/
prnt("OK\n");
return 0;
}
extern int8_t threequarter_fs;
extern openair0_config_t openair0_cfg[MAX_CARDS];
static int set_bwconfig(char *buf, int debug, telnet_printfunc_t prnt)
{
if (running)
ERROR_MSG_RET("cannot set parameters while L1 is running\n");
if (!buf)
ERROR_MSG_RET("need param: o1 bwconfig <BW>\n");
char *end = NULL;
if (NULL != (end = strchr(buf, '\n')))
*end = 0;
if (NULL != (end = strchr(buf, '\r')))
*end = 0;
gNB_MAC_INST *mac = RC.nrmac[0];
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL;
NR_BWP_t *initialUL = &scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
if (strcmp(buf, "40") == 0) {
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB = 641280;
frequencyInfoDL->absoluteFrequencyPointA = 640008;
AssertFatal(frequencyInfoUL->absoluteFrequencyPointA == NULL, "only handle TDD\n");
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = 106;
initialDL->locationAndBandwidth = 28875;
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = 106;
initialUL->locationAndBandwidth = 28875;
threequarter_fs = 1;
openair0_cfg[0].threequarter_fs = 1;
} else if (strcmp(buf, "20") == 0) {
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB = 641280;
frequencyInfoDL->absoluteFrequencyPointA = 640596;
AssertFatal(frequencyInfoUL->absoluteFrequencyPointA == NULL, "only handle TDD\n");
frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = 51;
initialDL->locationAndBandwidth = 13750;
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth = 51;
initialUL->locationAndBandwidth = 13750;
threequarter_fs = 0;
openair0_cfg[0].threequarter_fs = 0;
} else {
ERROR_MSG_RET("unhandled option %s\n", buf);
}
free(RC.nrmac[0]->sched_ctrlCommon);
RC.nrmac[0]->sched_ctrlCommon = NULL;
free_MIB_NR(mac->common_channels[0].mib);
mac->common_channels[0].mib = get_new_MIB_NR(scc);
// due to outrightly CRAZY memory handling in get_SIB1_NR(), we need to set
// some structures to zero to prevent that we shoot ourselves into the foot
//struct NR_SIB1 *xyz = rrc->carrier.siblock1->message.choice.c1->choice.systemInformationBlockType1;
//xyz->servingCellConfigCommon = NULL;
//free_SIB1_NR(rrc->carrier.siblock1);
const f1ap_served_cell_info_t *info = &mac->f1_config.setup_req->cell[0].info;
/*
NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, &info->plmn, into->nr_cellid, *info.tac);
rrc->carrier.SIB1 = calloc(NR_MAX_SIB_LENGTH / 8, sizeof(*rrc->carrier.SIB1));
AssertFatal(rrc->carrier.SIB1 != NULL, "out of memory\n");
rrc->carrier.sizeof_SIB1 = encode_SIB1_NR(sib1, rrc->carrier.SIB1, NR_MAX_SIB_LENGTH / 8);
rrc->carrier.siblock1 = sib1;
*/
nr_mac_configure_sib1(mac, &info->plmn, info->nr_cellid, *info->tac);
//nr_mac_config_scc(mac, scc, &mac->radio_config);
prnt("OK\n");
return 0;
}
extern int stop_L1L2(module_id_t gnb_id);
static int stop_modem(char *buf, int debug, telnet_printfunc_t prnt)
{
if (!running)
ERROR_MSG_RET("cannot stop, nr-softmodem not running\n");
/* make UEs out of sync and wait 20ms to ensure no PUCCH is scheduled. After
* a restart, the frame/slot numbers will be different, which "confuses" the
* scheduler, which has many PUCCH structures filled with expected frame/slot
* combinations that won't happen. */
const gNB_MAC_INST *mac = RC.nrmac[0];
UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) {
it->UE_sched_ctrl.rrc_processing_timer = 1000;
}
usleep(50000);
stop_L1L2(0);
running = false;
prnt("OK\n");
return 0;
}
extern int start_L1L2(module_id_t gnb_id);
static int start_modem(char *buf, int debug, telnet_printfunc_t prnt)
{
if (running)
ERROR_MSG_RET("cannot start, nr-softmodem already running\n");
start_L1L2(0);
running = true;
prnt("OK\n");
return 0;
}
static telnetshell_cmddef_t o1cmds[] = {
{"stats", "", get_stats},
{"config", "[]", set_config},
{"bwconfig", "", set_bwconfig},
{"stop_modem", "", stop_modem},
{"start_modem", "", start_modem},
{"", "", NULL},
};
static telnetshell_vardef_t o1vars[] = {
{"", 0, 0, NULL}
};
void add_o1_cmds(void) {
add_telnetcmd("o1", o1vars, o1cmds);
}

View File

@@ -66,7 +66,9 @@ RUN apt-get update && \
WORKDIR /opt/oai-gnb/bin
COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/nr-softmodem ./
/oai-ran/cmake_targets/ran_build/build/nr-softmodem \
./
COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh
COPY --from=gnb-build \
@@ -79,6 +81,10 @@ COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/libldpc*.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_bearer.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_enb.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_o1.so \
/usr/local/lib/
# Now we are copying from builder-image the UHD files.

View File

@@ -149,6 +149,9 @@ f1ap_cudu_inst_t *getCxt(instance_t instanceP)
return &fake;
}
configmodule_interface_t *uniqCfg = NULL;
void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t gNB_ue_ngap_id) { };
int main(int argc, char **argv)
{
/// static configuration for NR at the moment

View File

@@ -548,6 +548,122 @@ void terminate_task(task_id_t task_id, module_id_t mod_id) {
//extern void free_transport(PHY_VARS_gNB *);
extern void nr_phy_free_RU(RU_t *);
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
int stop_L1L2(module_id_t gnb_id)
{
LOG_W(GNB_APP, "stopping nr-softmodem\n");
oai_exit = 1;
if (!RC.ru) {
LOG_F(GNB_APP, "no RU configured\n");
return -1;
}
/* stop trx devices, multiple carrier currently not supported by RU */
if (RC.ru[gnb_id]) {
AssertFatal(RC.ru[gnb_id]->rfdevice.trx_stop_func != NULL, "cannot call rfdevice.trx_stop_func(), is NULL\n");
RC.ru[gnb_id]->rfdevice.trx_stop_func(&RC.ru[gnb_id]->rfdevice);
LOG_I(GNB_APP, "turned off RU rfdevice\n");
/*
AssertFatal(RC.ru[gnb_id]->ifdevice.trx_stop_func != NULL, "cannot call ifdevice.trx_stop_func(), is NULL\n");
RC.ru[gnb_id]->ifdevice.trx_stop_func(&RC.ru[gnb_id]->ifdevice);
LOG_I(GNB_APP, "turned off RU ifdevice\n");
*/
}
/* these tasks/layers need to pick up new configuration */
if (RC.nb_nr_L1_inst > 0)
stop_gNB(RC.nb_nr_L1_inst);
if (RC.nb_RU > 0)
stop_RU(RC.nb_RU);
/* release memory used by the RU/gNB threads (incomplete), after all
* threads have been stopped (they partially use the same memory) */
for (int inst = 0; inst < RC.nb_RU; inst++) {
nr_phy_free_RU(RC.ru[inst]);
}
for (int inst = 0; inst < RC.nb_nr_L1_inst; inst++) {
phy_free_nr_gNB(RC.gNB[inst]);
}
oai_exit = 0;
return 0;
}
extern f1ap_tdd_info_t read_tdd_config(const NR_ServingCellConfigCommon_t *scc);
extern f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1);
/*
* Restart the nr-softmodem after it has been soft-stopped with stop_L1L2()
*/
int start_L1L2(module_id_t gnb_id)
{
//RU_t *ru = RC.ru[gnb_id];
//MessageDef *msg_p = NULL;
LOG_W(GNB_APP, "restarting nr-softmodem\n");
/* block threads */
sync_var = -1;
RC.gNB[gnb_id]->configured = 0;
extern void init_sched_response(void);
init_sched_response();
/*
RC.ru_mask |= (1 << ru->idx);
set_function_spec_param(RC.ru[gnb_id]);
LOG_I(GNB_APP, "attempting to create ITTI tasks\n");
*/
// No more rrc thread, as many race conditions are hidden behind
//int rc = itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL);
//AssertFatal(rc == 0, "could not create RRC task\n");
/* pass a reconfiguration request which will configure everything down to
* RC.eNB[i][j]->frame_parms, too */
/*
msg_p = itti_alloc_new_message(TASK_GNB_APP, 0, NRRRC_CONFIGURATION_REQ);
NRRRC_CONFIGURATION_REQ(msg_p) = RC.nrrrc[gnb_id]->configuration;
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg_p);
*/
gNB_MAC_INST *mac = RC.nrmac[0];
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
nr_mac_config_scc(mac, scc, &mac->radio_config);
NR_BCCH_BCH_Message_t *mib = mac->common_channels[0].mib;
const NR_BCCH_DL_SCH_Message_t *sib1 = mac->common_channels[0].sib1;
/* update existing config in F1 Setup request structures */
f1ap_setup_req_t *sr = mac->f1_config.setup_req;
DevAssert(sr->num_cells_available == 1);
f1ap_served_cell_info_t *info = &sr->cell[0].info;
DevAssert(info->mode == F1AP_MODE_TDD);
DevAssert(scc->tdd_UL_DL_ConfigurationCommon != NULL);
info->tdd = read_tdd_config(scc); /* updates radio config */
/* send gNB-DU configuration update to RRC */
f1ap_gnb_du_configuration_update_t update = {
.transaction_id = 1,
.num_cells_to_modify = 1,
};
update.cell_to_modify[0].old_nr_cellid = info->nr_cellid;
update.cell_to_modify[0].info = *info;
update.cell_to_modify[0].sys_info = get_sys_info(mib, sib1);
mac->mac_rrc.gnb_du_configuration_update(&update);
//sleep(2);
init_NR_RU(config_get_if(), NULL);
start_NR_RU();
wait_RUs();
init_eNB_afterRU();
printf("Sending sync to all threads\n");
pthread_mutex_lock(&sync_mutex);
sync_var=0;
pthread_cond_broadcast(&sync_cond);
pthread_mutex_unlock(&sync_mutex);
return 0;
}
static void wait_nfapi_init(char *thread_name) {
printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
pthread_mutex_lock( &nfapi_sync_mutex );

View File

@@ -168,6 +168,9 @@ nr_bler_struct nr_bler_data[NR_NUM_MCS];
static void init_bler_table(char*);
// to be removed
void nr_mac_trigger_ul_failure(int rnti) { abort(); }
/*---------------------BMC: timespec helpers -----------------------------*/
struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };

253
gnb_20.conf Normal file
View File

@@ -0,0 +1,253 @@
Active_gNBs = ( "gNB-DU-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
gNB_name = "gNB-DU-in-docker";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1 }) });
nr_cellid = 12345678L;
////////// Physical parameters:
#min_rxtxtime = 6;
force_256qam_off = 0;
do_CSIRS = 0;
do_SRS = 0;
pdcch_ConfigSIB1 = (
{
controlResourceSetZero = 12;
searchSpaceZero = 0;
}
);
servingCellConfigCommon = (
{
#spCellConfigCommon
physCellId = 0;
# downlinkConfigCommon
#frequencyInfoDL
# this is 3300.30 MHz + (19 PRBs + 10 SCs)@30kHz SCS (GSCN: 7715)
absoluteFrequencySSB = 641280; #620736;
dl_frequencyBand = 78;
# this is 3300.30 MHz
dl_absoluteFrequencyPointA = 640596; #620052;
#scs-SpecificCarrierList
dl_offstToCarrier = 0;
# subcarrierSpacing
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 51;
#initialDownlinkBWP
#genericParameters
# this is RBstart=27,L=48 (275*(L-1))+RBstart
initialDLBWPlocationAndBandwidth = 13750;
# 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 = 51;
pMax = 20;
#initialUplinkBWP
#genericParameters
initialULBWPlocationAndBandwidth = 13750;
# 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;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ( { ipv4 = "192.168.70.132";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp3s0";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "16.1.1.2";
GNB_INTERFACE_NAME_FOR_NGU = "enp3s0";
GNB_IPV4_ADDRESS_FOR_NGU = "16.1.1.2";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 230; # 200; after test in lab
pucch_TargetSNRx10 = 200;
ulsch_max_frame_inactivity = 1;
ul_max_mcs = 16;
min_grant_prb = 20;
}
);
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 = 6; # 8; after test in lab
att_rx = 6; # 8; after test in lab
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 115; #120;
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";
}
);
log_config :
{
global_log_level ="info";
hw_log_level ="info";
phy_log_level ="info";
mac_log_level ="info";
rlc_log_level ="info";
pdcp_log_level ="info";
rrc_log_level ="info";
ngap_log_level ="info";
f1ap_log_level ="info";
};

267
gnb_40.conf Normal file
View File

@@ -0,0 +1,267 @@
Active_gNBs = ( "gNB-DU-in-docker");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
gNBs =
(
{
////////// Identification parameters:
gNB_ID = 0xe00;
# cell_type = "CELL_MACRO_GNB";
gNB_name = "gNB-DU-in-docker";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1 }) });
nr_cellid = 12345678L;
////////// Physical parameters:
#min_rxtxtime = 6;
force_256qam_off = 0;
do_CSIRS = 0;
do_SRS = 0;
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;
}
);
# ------- SCTP definitions
SCTP :
{
# Number of streams to use in input/output
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters:
amf_ip_address = ( { ipv4 = "192.168.70.132";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_NG_AMF = "enp3s0";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "16.1.1.2";
GNB_INTERFACE_NAME_FOR_NGU = "enp3s0";
GNB_IPV4_ADDRESS_FOR_NGU = "16.1.1.2";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
}
);
e2_agent = {
#address = "10.0.0.4";
address = "172.23.100.25";
sm_dir = "/usr/local/lib/flexric/"
}
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 230; # 200; after test in lab
pucch_TargetSNRx10 = 200;
ulsch_max_frame_inactivity = 1;
ul_max_mcs = 16;
min_grant_prb = 20;
}
);
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 = 6; # 8; after test in lab
att_rx = 6; # 8; after test in lab
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 115;
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";
};
log_config :
{
global_log_level ="info";
hw_log_level ="info";
phy_log_level ="info";
mac_log_level ="info";
rlc_log_level ="info";
pdcp_log_level ="info";
rrc_log_level ="info";
ngap_log_level ="info";
f1ap_log_level ="info";
};

View File

@@ -550,11 +550,6 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config)
nr_init_frame_parms(gNB_config, fp);
if (RC.gNB[Mod_id]->configured == 1) {
LOG_E(PHY,"Already gNB already configured, do nothing\n");
return;
}
fd_occasion = 0;
nfapi_nr_prach_config_t *prach_config = &gNB_config->prach_config;
short_sequence = prach_config->prach_sequence_length.value;

View File

@@ -217,4 +217,8 @@ void nr_phy_free_RU(RU_t *ru)
}
}
free_and_zero(ru->common.sync_corr);
PHY_VARS_gNB *gNB0= ru->gNB_list[0];
gNB0->num_RU--;
DevAssert(gNB0->num_RU >= 0);
}

View File

@@ -27,11 +27,14 @@ MESSAGE_DEF(F1AP_DU_REGISTER_REQ, MESSAGE_PRIORITY_MED, f1ap_du_register_req_t,
MESSAGE_DEF(F1AP_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_setup_req_t , f1ap_setup_req)
MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_acknowledge_t , f1ap_gnb_cu_configuration_update_acknowledge)
MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_failure_t , f1ap_gnb_cu_configuration_update_failure)
MESSAGE_DEF(F1AP_GNB_DU_CONFIGURATION_UPDATE, MESSAGE_PRIORITY_MED, f1ap_gnb_du_configuration_update_t, f1ap_gnb_du_configuration_update)
/* F1AP -> eNB_DU or eNB_CU_RRC -> F1AP application layer messages */
MESSAGE_DEF(F1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, f1ap_setup_resp_t , f1ap_setup_resp)
MESSAGE_DEF(F1AP_SETUP_FAILURE , MESSAGE_PRIORITY_MED, f1ap_setup_failure_t , f1ap_setup_failure)
MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_t , f1ap_gnb_cu_configuration_update)
MESSAGE_DEF(F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE , MESSAGE_PRIORITY_MED, f1ap_gnb_du_configuration_update_acknowledge_t, f1ap_gnb_du_configuration_update_acknowledge)
MESSAGE_DEF(F1AP_GNB_DU_CONFIGURATION_UPDATE_FAILURE , MESSAGE_PRIORITY_MED, f1ap_gnb_du_configuration_update_failure_t, f1ap_gnb_du_configuration_update_failure)
/* F1AP -> RRC to inform about lost connection */
MESSAGE_DEF(F1AP_LOST_CONNECTION, MESSAGE_PRIORITY_MED, f1ap_lost_connection_t, f1ap_lost_connection)

View File

@@ -39,6 +39,10 @@
#define F1AP_GNB_CU_CONFIGURATION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update
#define F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_acknowledge
#define F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update_failure
#define F1AP_GNB_DU_CONFIGURATION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_du_configuration_update
#define F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_du_configuration_update_acknowledge
#define F1AP_GNB_DU_CONFIGURATION_UPDATE_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_du_configuration_update_failure
#define F1AP_SETUP_FAILURE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_failure
#define F1AP_LOST_CONNECTION(mSGpTR) (mSGpTR)->ittiMsg.f1ap_lost_connection
@@ -127,7 +131,7 @@ typedef struct f1ap_served_cell_info_t {
// Number of slide support items (max 16, could be increased to as much as 1024)
uint16_t num_ssi;
uint8_t sst;
uint8_t sd;
uint32_t sd;
f1ap_mode_t mode;
union {
@@ -246,6 +250,58 @@ typedef struct f1ap_gnb_cu_configuration_update_failure_s {
uint16_t criticality_diagnostics;
} f1ap_gnb_cu_configuration_update_failure_t;
/*DU configuration messages*/
typedef struct f1ap_gnb_du_configuration_update_s {
/*TODO UPDATE TO SUPPORT DU CONFIG*/
/* Transaction ID */
uint64_t transaction_id;
/// int cells_to_add
uint16_t num_cells_to_add;
struct {
f1ap_served_cell_info_t info;
f1ap_gnb_du_system_info_t *sys_info;
} cell_to_add[F1AP_MAX_NB_CELLS];
/// int cells_to_modify
uint16_t num_cells_to_modify;
struct {
f1ap_plmn_t old_plmn;
uint64_t old_nr_cellid; // NR Global Cell Id
f1ap_served_cell_info_t info;
f1ap_gnb_du_system_info_t *sys_info;
} cell_to_modify[F1AP_MAX_NB_CELLS];
/// int cells_to_delete
uint16_t num_cells_to_delete;
struct {
// NR CGI
f1ap_plmn_t plmn;
uint64_t nr_cellid; // NR Global Cell Id
} cell_to_delete[F1AP_MAX_NB_CELLS];
/// string holding gNB_CU_name
uint64_t *gNB_DU_ID;
} f1ap_gnb_du_configuration_update_t;
typedef struct f1ap_gnb_du_configuration_update_acknowledge_s {
/// ulong transaction id
uint64_t transaction_id;
/// string holding gNB_CU_name
char *gNB_CU_name;
/// number of DU cells to activate
uint16_t num_cells_to_activate; //0< num_cells_to_activate <= 512;
served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS];
} f1ap_gnb_du_configuration_update_acknowledge_t;
typedef struct f1ap_gnb_du_configuration_update_failure_s {
/*TODO UPDATE TO SUPPORT DU CONFIG*/
uint16_t cause;
uint16_t time_to_wait;
uint16_t criticality_diagnostics;
} f1ap_gnb_du_configuration_update_failure_t;
typedef struct f1ap_dl_rrc_message_s {
uint32_t gNB_CU_ue_id;

View File

@@ -412,6 +412,8 @@ typedef struct NRRrcConfigurationReq_s {
uint16_t mnc[PLMN_LIST_MAX_SIZE];
uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE];
uint8_t num_plmn;
int sd;
int sst;
bool um_on_default_drb;
bool enable_sdap;

View File

@@ -431,17 +431,337 @@ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *
int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
{
AssertFatal(1==0,"Not implemented yet\n");
LOG_D(F1AP, "CU_handle_gNB_DU_CONFIGURATION_UPDATE\n");
F1AP_GNBDUConfigurationUpdate_t *container;
F1AP_GNBDUConfigurationUpdateIEs_t *ie;
int i = 0;
DevAssert(pdu != NULL);
container = &pdu->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate;
/* gNB DU Configuration Update == Non UE-related procedure -> stream 0 */
if (stream != 0) {
LOG_W(F1AP, "[SCTP %d] Received f1 setup request on stream != 0 (%d)\n",
assoc_id, stream);
}
MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE);
message_p->ittiMsgHeader.originInstance = assoc_id;
f1ap_gnb_du_configuration_update_t *req = &F1AP_GNB_DU_CONFIGURATION_UPDATE(message_p);
/* 3GPP TS 38.473 Transaction ID*/
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true);
req->transaction_id = ie->value.choice.TransactionID;
LOG_D(F1AP, "req->transaction_id %lu \n", req->transaction_id);
/* 3GPP TS 38.473 Served Cells To Add List */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container,
F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List, false);
if(ie!=NULL){
req->num_cells_to_add = ie->value.choice.Served_Cells_To_Add_List.list.count;
LOG_D(F1AP, "req->num_cells_to_add %d \n", req->num_cells_to_add);
for (i=0; i<req->num_cells_to_add; i++) {
F1AP_Served_Cells_To_Add_Item_t *served_cells_item = &((F1AP_Served_Cells_To_Add_ItemIEs_t *)
ie->value.choice.Served_Cells_To_Add_List.list.array[i])->
value.choice.Served_Cells_To_Add_Item;
F1AP_Served_Cell_Information_t *servedCellInformation= &served_cells_item->served_Cell_Information;
/* tac */
if (servedCellInformation->fiveGS_TAC) {
req->cell_to_add[i].info.tac = malloc(sizeof(*req->cell_to_add[i].info.tac));
AssertFatal(req->cell_to_add[i].info.tac != NULL, "out of memory\n");
OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell_to_add[i].info.tac);
LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_add[i].info.tac);
}
/* - nRCGI */
TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity),
req->cell_to_add[i].info.plmn.mcc,
req->cell_to_add[i].info.plmn.mnc,
req->cell_to_add[i].info.plmn.mnc_digit_length);
// NR cellID
BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity,
req->cell_to_add[i].info.nr_cellid);
LOG_D(F1AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id,
req->cell_to_add[i].info.plmn.mcc,
req->cell_to_add[i].info.plmn.mnc,
(long long unsigned int)req->cell_to_add[i].info.nr_cellid);
/* - nRPCI */
req->cell_to_add[i].info.nr_pci = servedCellInformation->nRPCI;
LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_add[i].info.nr_pci);
// FDD Cells
if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_fDD) {
req->cell_to_add[i].info.mode = F1AP_MODE_FDD;
f1ap_fdd_info_t *FDDs = &req->cell_to_add[i].info.fdd;
F1AP_FDD_Info_t * fDD_Info=servedCellInformation->nR_Mode_Info.choice.fDD;
FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN;
AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n");
for (int f=0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) {
F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f];
FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr;
AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n");
}
FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN;
int dlBands=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count;
AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n");
for (int dlB=0; dlB < dlBands; dlB++) {
F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB];
FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr;
int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count;
AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n");
}
FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS;
FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB];
FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS;
FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB];
} else if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_tDD) {
req->cell_to_add[i].info.mode = F1AP_MODE_TDD;
f1ap_tdd_info_t *TDDs = &req->cell_to_add[i].info.tdd;
F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD;
TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN;
AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n");
for (int f=0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) {
struct F1AP_FreqBandNrItem * FreqItem=tDD_Info->nRFreqInfo.freqBandListNr.list.array[f];
TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr;
int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count;
AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n");
}
TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS;
TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB];
} else {
AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present);
}
struct F1AP_GNB_DU_System_Information * DUsi=served_cells_item->gNB_DU_System_Information;
// System Information
req->cell_to_add[i].sys_info = calloc(1, sizeof(*req->cell_to_add[i].sys_info));
AssertFatal(req->cell_to_add[i].sys_info != NULL, "out of memory\n");
f1ap_gnb_du_system_info_t *sys_info = req->cell_to_add[i].sys_info;
/* mib */
sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char));
memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size);
sys_info->mib_length = DUsi->mIB_message.size;
/* sib1 */
sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char));
memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size);
sys_info->sib1_length = DUsi->sIB1_message.size;
}
}
else {
req->num_cells_to_add = 0;
}
/* 3GPP TS 38.473 Served Cells To Modify List */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List, false);
if(ie){
req->num_cells_to_modify = ie->value.choice.Served_Cells_To_Modify_List.list.count;
LOG_D(F1AP, "req->num_cells_to_modify %d \n", req->num_cells_to_modify);
for (i=0; i<req->num_cells_to_modify; i++) {
F1AP_Served_Cells_To_Modify_Item_t *served_cells_item = &((F1AP_Served_Cells_To_Modify_ItemIEs_t *)
ie->value.choice.Served_Cells_To_Modify_List.list.array[i])->
value.choice.Served_Cells_To_Modify_Item;
/* OLD NRCGI */
TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity),
req->cell_to_modify[i].old_plmn.mcc,
req->cell_to_modify[i].old_plmn.mnc,
req->cell_to_modify[i].old_plmn.mnc_digit_length);
BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity,
req->cell_to_modify[i].old_nr_cellid);
F1AP_Served_Cell_Information_t *servedCellInformation= &served_cells_item->served_Cell_Information;
/* SERVED CELL INFORMATION*/
/* tac */
if (servedCellInformation->fiveGS_TAC) {
req->cell_to_modify[i].info.tac = malloc(sizeof(*req->cell_to_modify[i].info.tac));
AssertFatal(req->cell_to_modify[i].info.tac != NULL, "out of memory\n");
OCTET_STRING_TO_INT16(servedCellInformation->fiveGS_TAC, *req->cell_to_modify[i].info.tac);
LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_modify[i].info.tac);
}
/* - nRCGI */
TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity),
req->cell_to_modify[i].info.plmn.mcc,
req->cell_to_modify[i].info.plmn.mnc,
req->cell_to_modify[i].info.plmn.mnc_digit_length);
// NR cellID
BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity,
req->cell_to_modify[i].info.nr_cellid);
LOG_D(F1AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id,
req->cell_to_modify[i].info.plmn.mcc,
req->cell_to_modify[i].info.plmn.mnc,
(long long unsigned int)req->cell_to_modify[i].info.nr_cellid);
/* - nRPCI */
req->cell_to_modify[i].info.nr_pci = servedCellInformation->nRPCI;
LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_modify[i].info.nr_pci);
// FDD Cells
if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_fDD) {
req->cell_to_modify[i].info.mode = F1AP_MODE_FDD;
f1ap_fdd_info_t *FDDs = &req->cell_to_modify[i].info.fdd;
F1AP_FDD_Info_t * fDD_Info=servedCellInformation->nR_Mode_Info.choice.fDD;
FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN;
AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n");
for (int f=0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) {
F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f];
FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr;
AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n");
}
FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN;
int dlBands=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count;
AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n");
for (int dlB=0; dlB < dlBands; dlB++) {
F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB];
FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr;
int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count;
AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n");
}
FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS;
FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB];
FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS;
FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB];
} else if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_tDD) {
req->cell_to_modify[i].info.mode = F1AP_MODE_TDD;
f1ap_tdd_info_t *TDDs = &req->cell_to_modify[i].info.tdd;
F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD;
TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN;
AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n");
for (int f=0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) {
struct F1AP_FreqBandNrItem * FreqItem=tDD_Info->nRFreqInfo.freqBandListNr.list.array[f];
TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr;
int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count;
AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n");
}
TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS;
TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB];
} else {
AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present);
}
//TODO: Measurement Config
/*gNB DU SYSTEM INFORMATION */
struct F1AP_GNB_DU_System_Information * DUsi=served_cells_item->gNB_DU_System_Information;
if(DUsi!=NULL){
// System Information
req->cell_to_modify[i].sys_info = calloc(1, sizeof(*req->cell_to_modify[i].sys_info));
AssertFatal(req->cell_to_modify[i].sys_info != NULL, "out of memory\n");
f1ap_gnb_du_system_info_t *sys_info = req->cell_to_modify[i].sys_info;
/* mib */
sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char));
AssertFatal(req->cell_to_modify[i].sys_info->mib != NULL, "out of memory\n");
memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size);
sys_info->mib_length = DUsi->mIB_message.size;
/* sib1 */
sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char));
AssertFatal(req->cell_to_modify[i].sys_info->sib1 != NULL, "out of memory\n");
memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size);
sys_info->sib1_length = DUsi->sIB1_message.size;
}
}
} else {
req->num_cells_to_modify = 0;
}
/* 3GPP TS 38.473 Served Cells To Delete List */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List, false);
if(ie){
req->num_cells_to_delete = ie->value.choice.Served_Cells_To_Delete_List.list.count;
LOG_D(F1AP, "req->num_cells_to_delete %d \n", req->num_cells_to_delete);
for (i=0; i<req->num_cells_to_delete; i++) {
F1AP_Served_Cells_To_Delete_Item_t *served_cells_item = &((F1AP_Served_Cells_To_Delete_ItemIEs_t *)
ie->value.choice.Served_Cells_To_Delete_List.list.array[i])->
value.choice.Served_Cells_To_Delete_Item;
/* - Old nRCGI */
TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity),
req->cell_to_delete[i].plmn.mcc,
req->cell_to_delete[i].plmn.mnc,
req->cell_to_delete[i].plmn.mnc_digit_length);
// NR cellID
BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity,
req->cell_to_delete[i].nr_cellid);
LOG_D(F1AP, "[SCTP %d] Received nRCGI to delete: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id,
req->cell_to_delete[i].plmn.mcc,
req->cell_to_delete[i].plmn.mnc,
(long long unsigned int)req->cell_to_delete[i].nr_cellid);
}
} else {
req->num_cells_to_delete = 0;
}
/* 3GPP TS 38.473 Cells Status List */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cells_Status_List, false);
/* 3GPP TS 38.473 Dedicated SI Delivery Needed UE List */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Dedicated_SIDelivery_NeededUE_List, false);
/* 3GPP TS 38.473 gNB-DU ID */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_ID, false);
if(ie!=NULL)
asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID,req->gNB_DU_ID);
/* 3GPP TS 38.473 gNB-DU TNL Association To Remove List */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_GNB_DU_TNL_Association_To_Remove_List, false);
LOG_D(F1AP, "Sending F1AP_GNB_DU_CONFIGURATION_UPDATE ITTI message \n");
itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p);
return 0;
}
int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id,
F1AP_GNBDUConfigurationUpdateFailure_t *GNBDUConfigurationUpdateFailure) {
f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure) {
AssertFatal(1==0,"Not implemented yet\n");
}
int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id,
F1AP_GNBDUConfigurationUpdateAcknowledge_t *GNBDUConfigurationUpdateAcknowledge) {
AssertFatal(1==0,"Not implemented yet\n");
f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge) {
F1AP_F1AP_PDU_t pdu = {};
uint8_t *buffer;
uint32_t len;
/* Create */
/* 0. Message */
pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome;
asn1cCalloc(pdu.choice.successfulOutcome, succOut);
succOut->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate;
succOut->criticality = F1AP_Criticality_reject;
succOut->value.present = F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge ;
F1AP_GNBDUConfigurationUpdateAcknowledge_t *ack = &succOut->value.choice.GNBDUConfigurationUpdateAcknowledge;
/* Mandatory */
/* Transaction Id */
asn1cSequenceAdd(ack->protocolIEs.list, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie1);
ie1->id = F1AP_ProtocolIE_ID_id_TransactionID;
ie1->criticality = F1AP_Criticality_reject;
ie1->value.present = F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID;
ie1->value.choice.TransactionID = GNBDUConfigurationUpdateAcknowledge->transaction_id;
/* Todo add optional fields */
/* encode */
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n");
return -1;
}
LOG_DUMPMSG(F1AP, LOG_DUMP_CHAR, buffer, len, "F1AP gNB-DU CONFIGURATION UPDATE : ");
ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu);
f1ap_itti_send_sctp_data_req(assoc_id, buffer, len);
return 0;
}
/*

View File

@@ -62,10 +62,10 @@ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *
int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id,
F1AP_GNBDUConfigurationUpdateFailure_t *GNBDUConfigurationUpdateFailure);
f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure);
int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id,
F1AP_GNBDUConfigurationUpdateAcknowledge_t *GNBDUConfigurationUpdateAcknowledge);
f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge);
/*
* gNB-CU Configuration Update

View File

@@ -179,6 +179,9 @@ void *F1AP_CU_task(void *arg) {
&F1AP_GNB_CU_CONFIGURATION_UPDATE(received_msg));
break;
case F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE:
CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(assoc_id,&F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(received_msg));
break;
case F1AP_DL_RRC_MESSAGE: // from rrc
CU_send_DL_RRC_MESSAGE_TRANSFER(assoc_id,
&F1AP_DL_RRC_MESSAGE(received_msg));

View File

@@ -38,8 +38,6 @@
#include "rrc_extern.h"
#include "openair2/RRC/NR/rrc_gNB_NGAP.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
static void setQos(F1AP_NonDynamic5QIDescriptor_t **toFill)
{
@@ -163,7 +161,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
for (int i=0; i<1; i++) {
asn1cSequenceAdd(ie7->value.choice.Candidate_SpCell_List.list,F1AP_Candidate_SpCell_ItemIEs_t, candidate_spCell_item_ies);
candidate_spCell_item_ies->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_Item; // 91
candidate_spCell_item_ies->criticality = F1AP_Criticality_reject;
candidate_spCell_item_ies->criticality = F1AP_Criticality_ignore;
candidate_spCell_item_ies->value.present = F1AP_Candidate_SpCell_ItemIEs__value_PR_Candidate_SpCell_Item;
/* 7.1 Candidate_SpCell_Item */
F1AP_Candidate_SpCell_Item_t *candidate_spCell_item=
@@ -253,7 +251,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
for (int i=0; i<f1ap_ue_context_setup_req->srbs_to_be_setup_length; i++) {
asn1cSequenceAdd(ie11->value.choice.SRBs_ToBeSetup_List.list, F1AP_SRBs_ToBeSetup_ItemIEs_t, srbs_toBeSetup_item_ies);
srbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item; // 73
srbs_toBeSetup_item_ies->criticality = F1AP_Criticality_ignore;
srbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject;
srbs_toBeSetup_item_ies->value.present = F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item;
/* 11.1 SRBs_ToBeSetup_Item */
F1AP_SRBs_ToBeSetup_Item_t *srbs_toBeSetup_item=&srbs_toBeSetup_item_ies->value.choice.SRBs_ToBeSetup_Item;
@@ -503,19 +501,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
/* 12.1.3 uLUPTNLInformation_ToBeSetup_List */
for (int j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) {
/*Use a dummy teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU*/
/* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU */
transport_layer_addr_t addr = { .length= 32, .buffer= { 0 } };
f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid = newGtpuCreateTunnel(getCxt(0)->gtpInst,
f1ap_ue_context_setup_req->gNB_CU_ue_id,
f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id,
f1ap_ue_context_setup_req->drbs_to_be_setup[i].drb_id,
0xFFFF, // We will set the right value from DU answer
-1, // no qfi
addr, // We will set the right value from DU answer
f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_dl_tnl[0].port,
cu_f1u_data_req,
NULL);
DevAssert(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid > 0);
/* 12.3.1 ULTunnels_ToBeSetup_Item */
asn1cSequenceAdd(drbs_toBeSetup_item->uLUPTNLInformation_ToBeSetup_List.list,
F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item);
@@ -590,7 +576,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu
if(f1ap_ue_context_setup_req->rrc_container_length > 0) {
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie14);
ie14->id = F1AP_ProtocolIE_ID_id_RRCContainer;
ie14->criticality = F1AP_Criticality_reject;
ie14->criticality = F1AP_Criticality_ignore;
ie14->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer;
OCTET_STRING_fromBuf(&ie14->value.choice.RRCContainer, (const char *)f1ap_ue_context_setup_req->rrc_container,
f1ap_ue_context_setup_req->rrc_container_length);
@@ -688,11 +674,6 @@ int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_
F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address);
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(instance)->gtpInst,
f1ap_ue_context_setup_resp->gNB_DU_ue_id,
(ebi_t)drbs_setup_item_p->dRBID,
drb_p->up_dl_tnl[0].tl_address,
drb_p->up_dl_tnl[0].teid);
}
}
@@ -1569,9 +1550,6 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte
&drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item;
/* dRBID */
drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id;
newGtpuDeleteOneTunnel(getCxt(0)->gtpInst,
f1ap_ue_context_modification_req->gNB_CU_ue_id,
f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
}
}
@@ -1644,11 +1622,6 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t
F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel;
BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address);
OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid);
GtpuUpdateTunnelOutgoingAddressAndTeid(getCxt(instance)->gtpInst,
f1ap_ue_context_modification_resp->gNB_CU_ue_id,
(ebi_t)drbs_setupmod_item_p->dRBID,
drb_p->up_dl_tnl[0].tl_address,
drb_p->up_dl_tnl[0].teid);
}
}
// SRBs_FailedToBeSetupMod_List

View File

@@ -83,12 +83,145 @@ int DU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint3
AssertFatal(1==0,"Not implemented yet\n");
}
/*
F1 Setup
*/
static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_cell_info_t *c)
{
/* 4.1.1 served cell Information */
F1AP_Served_Cell_Information_t scell_info = {0};
addnRCGI(scell_info.nRCGI, c);
/* - nRPCI */
scell_info.nRPCI = c->nr_pci; // int 0..1007
/* - fiveGS_TAC */
if (c->tac != NULL) {
uint32_t tac = htonl(*c->tac);
asn1cCalloc(scell_info.fiveGS_TAC, netOrder);
OCTET_STRING_fromBuf(netOrder, ((char *)&tac) + 1, 3);
}
/* - Configured_EPS_TAC */
if (0) {
scell_info.configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t));
OCTET_STRING_fromBuf(scell_info.configured_EPS_TAC, "2", 2);
}
/* servedPLMN information */
asn1cSequenceAdd(scell_info.servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item);
MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity);
F1AP_NR_Mode_Info_t *nR_Mode_Info = &scell_info.nR_Mode_Info;
F1AP_ProtocolExtensionContainer_10696P34_t *p = calloc(1, sizeof(*p));
servedPLMN_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p;
asn1cSequenceAdd(p->list, F1AP_ServedPLMNs_ItemExtIEs_t, served_plmns_itemExtIEs);
served_plmns_itemExtIEs->criticality = F1AP_Criticality_ignore;
served_plmns_itemExtIEs->id = F1AP_ProtocolIE_ID_id_TAISliceSupportList;
served_plmns_itemExtIEs->extensionValue.present = F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList;
F1AP_SliceSupportList_t *slice_support_list = &served_plmns_itemExtIEs->extensionValue.choice.SliceSupportList;
AssertFatal(c->num_ssi == 1, "can only encode one slice\n");
for (int s = 0; s < c->num_ssi; s++) {
asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice);
INT8_TO_OCTET_STRING(c->sst, &slice->sNSSAI.sST);
if (c->sd != 0xffffff) {
asn1cCalloc(slice->sNSSAI.sD, tmp);
INT24_TO_OCTET_STRING(c->sd, tmp);
}
}
if (c->mode == F1AP_MODE_FDD) { // FDD
const f1ap_fdd_info_t *fdd = &c->fdd;
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD;
asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info);
/* FDD.1.1 UL NRFreqInfo ARFCN */
fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; // Integer
/* FDD.1.2 F1AP_SUL_Information */
/* FDD.1.3 freqBandListNr */
int ul_band = 1;
for (int j = 0; j < ul_band; j++) {
asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
/* FDD.1.3.1 freqBandIndicatorNr*/
nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band;
/* FDD.1.3.2 supportedSULBandList*/
}
/* FDD.2.1 DL NRFreqInfo ARFCN */
fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; // Integer
/* FDD.2.2 F1AP_SUL_Information */
/* FDD.2.3 freqBandListNr */
int dl_bands = 1;
for (int j = 0; j < dl_bands; j++) {
asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
/* FDD.2.3.1 freqBandIndicatorNr*/
nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band;
/* FDD.2.3.2 supportedSULBandList*/
} // for FDD : DL freq_Bands
/* FDD.3 UL Transmission Bandwidth */
fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs;
fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb);
/* FDD.4 DL Transmission Bandwidth */
fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs;
fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb);
} else if (c->mode == F1AP_MODE_TDD) {
const f1ap_tdd_info_t *tdd = &c->tdd;
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD;
asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info);
/* TDD.1.1 nRFreqInfo ARFCN */
tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn;
/* TDD.1.2 F1AP_SUL_Information */
/* TDD.1.3 freqBandListNr */
int bands = 1;
for (int j = 0; j < bands; j++) {
asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
/* TDD.1.3.1 freqBandIndicatorNr*/
nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band;
/* TDD.1.3.2 supportedSULBandList*/
}
/* TDD.2 transmission_Bandwidth */
tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs;
tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb);
} else {
AssertFatal(false, "unknown mode %d\n", c->mode);
}
/* - measurementTimingConfiguration */
char *measurementTimingConfiguration = c->measurement_timing_information;
OCTET_STRING_fromBuf(&scell_info.measurementTimingConfiguration,
measurementTimingConfiguration,
strlen(measurementTimingConfiguration));
return scell_info;
}
static F1AP_GNB_DU_System_Information_t *encode_system_info(const f1ap_gnb_du_system_info_t *sys_info)
{
if (sys_info == NULL)
return NULL; /* optional: can be NULL */
F1AP_GNB_DU_System_Information_t *enc_sys_info = calloc(1, sizeof(*enc_sys_info));
AssertFatal(enc_sys_info != NULL, "out of memory\n");
AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n");
OCTET_STRING_fromBuf(&enc_sys_info->mIB_message, (const char *)sys_info->mib, sys_info->mib_length);
AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n");
OCTET_STRING_fromBuf(&enc_sys_info->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length);
return enc_sys_info;
}
// SETUP REQUEST
int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req)
int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setup_req)
{
F1AP_F1AP_PDU_t pdu= {0};
uint8_t *buffer;
@@ -139,151 +272,16 @@ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req)
for (int i=0; i<num_cells_available; i++) {
/* mandatory */
/* 4.1 served cells item */
f1ap_served_cell_info_t *cell = &setup_req->cell[i].info;
const f1ap_served_cell_info_t *cell = &setup_req->cell[i].info;
const f1ap_gnb_du_system_info_t *sys_info = setup_req->cell[i].sys_info;
asn1cSequenceAdd(ieCells->value.choice.GNB_DU_Served_Cells_List.list,
F1AP_GNB_DU_Served_Cells_ItemIEs_t, duServedCell);
duServedCell->id = F1AP_ProtocolIE_ID_id_GNB_DU_Served_Cells_Item;
duServedCell->criticality = F1AP_Criticality_reject;
duServedCell->value.present = F1AP_GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item;
F1AP_GNB_DU_Served_Cells_Item_t *gnb_du_served_cells_item=&duServedCell->value.choice.GNB_DU_Served_Cells_Item;
/* 4.1.1 served cell Information */
F1AP_Served_Cell_Information_t *served_cell_information= &gnb_du_served_cells_item->served_Cell_Information;
addnRCGI(served_cell_information->nRCGI, cell);
/* - nRPCI */
served_cell_information->nRPCI = cell->nr_pci; // int 0..1007
/* - fiveGS_TAC */
if (cell->tac != NULL) {
uint32_t tac=htonl(*cell->tac);
asn1cCalloc(served_cell_information->fiveGS_TAC, netOrder);
OCTET_STRING_fromBuf(netOrder, ((char *)&tac)+1, 3);
}
/* - Configured_EPS_TAC */
if(0) {
served_cell_information->configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t));
OCTET_STRING_fromBuf(served_cell_information->configured_EPS_TAC, "2", 2);
}
/* servedPLMN information */
asn1cSequenceAdd(served_cell_information->servedPLMNs.list, F1AP_ServedPLMNs_Item_t,servedPLMN_item);
MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity);
// // /* - CHOICE NR-MODE-Info */
F1AP_NR_Mode_Info_t *nR_Mode_Info= &served_cell_information->nR_Mode_Info;
F1AP_ProtocolExtensionContainer_10696P34_t *p = calloc(1, sizeof(*p));
servedPLMN_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *) p;
asn1cSequenceAdd(p->list, F1AP_ServedPLMNs_ItemExtIEs_t , served_plmns_itemExtIEs);
served_plmns_itemExtIEs->criticality = F1AP_Criticality_ignore;
served_plmns_itemExtIEs->id = F1AP_ProtocolIE_ID_id_TAISliceSupportList;
served_plmns_itemExtIEs->extensionValue.present = F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList;
F1AP_SliceSupportList_t *slice_support_list = &served_plmns_itemExtIEs->extensionValue.choice.SliceSupportList;
/* get list of sst/sd from configuration file */
paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC;
paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
char sstr[100];
/* TODO: be sure that %d in the line below is at the right place */
sprintf(sstr, "%s.[%d].%s.[0]", GNB_CONFIG_STRING_GNB_LIST, i, GNB_CONFIG_STRING_PLMN_LIST);
config_getlist(config_get_if(), &SNSSAIParamList, SNSSAIParams, sizeofArray(SNSSAIParams), sstr);
AssertFatal(SNSSAIParamList.numelt > 0, "no slice configuration found (snssaiList in the configuration file)\n");
AssertFatal(SNSSAIParamList.numelt <= 1024, "maximum size for slice support list is 1024, see F1AP 38.473 9.3.1.37\n");
for (int s = 0; s < SNSSAIParamList.numelt; s++) {
uint32_t sst;
uint32_t sd;
bool has_sd;
sst = *SNSSAIParamList.paramarray[s][GNB_SLICE_SERVICE_TYPE_IDX].uptr;
has_sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr != 0xffffff;
asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice);
INT8_TO_OCTET_STRING(sst, &slice->sNSSAI.sST);
if (has_sd) {
sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr;
asn1cCalloc(slice->sNSSAI.sD, tmp);
INT24_TO_OCTET_STRING(sd, tmp);
}
}
if (setup_req->cell[i].info.mode == F1AP_MODE_FDD) { // FDD
const f1ap_fdd_info_t *fdd = &setup_req->cell[i].info.fdd;
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD;
asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info);
/* FDD.1 UL NRFreqInfo */
/* FDD.1.1 UL NRFreqInfo ARFCN */
fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; // Integer
/* FDD.1.2 F1AP_SUL_Information */
/* FDD.1.3 freqBandListNr */
int fdd_ul_num_available_freq_Bands = 1;
for (int fdd_ul_j=0; fdd_ul_j<fdd_ul_num_available_freq_Bands; fdd_ul_j++) {
asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
/* FDD.1.3.1 freqBandIndicatorNr*/
nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band;
/* FDD.1.3.2 supportedSULBandList*/
} // for FDD : UL freq_Bands
/* FDD.2 DL NRFreqInfo */
/* FDD.2.1 DL NRFreqInfo ARFCN */
fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; // Integer
/* FDD.2.2 F1AP_SUL_Information */
/* FDD.2.3 freqBandListNr */
int fdd_dl_num_available_freq_Bands = 1;
for (int fdd_dl_j=0; fdd_dl_j<fdd_dl_num_available_freq_Bands; fdd_dl_j++) {
asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
/* FDD.2.3.1 freqBandIndicatorNr*/
nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band;
/* FDD.2.3.2 supportedSULBandList*/
} // for FDD : DL freq_Bands
/* FDD.3 UL Transmission Bandwidth */
fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs;
fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb);
/* FDD.4 DL Transmission Bandwidth */
fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs;
fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb);
} else if (setup_req->cell[i].info.mode == F1AP_MODE_TDD) { // TDD
const f1ap_tdd_info_t *tdd = &setup_req->cell[i].info.tdd;
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD;
asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info);
/* TDD.1 nRFreqInfo */
/* TDD.1.1 nRFreqInfo ARFCN */
tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn; // Integer
/* TDD.1.2 F1AP_SUL_Information */
/* TDD.1.3 freqBandListNr */
int tdd_num_available_freq_Bands = 1;
for (int j=0; j<tdd_num_available_freq_Bands; j++) {
asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
/* TDD.1.3.1 freqBandIndicatorNr*/
nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band;
/* TDD.1.3.2 supportedSULBandList*/
} // for TDD : freq_Bands
/* TDD.2 transmission_Bandwidth */
tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs;
tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb);
} else {
AssertFatal(false, "unknown mode %d\n", setup_req->cell[i].info.mode);
}
/* - measurementTimingConfiguration */
char *measurementTimingConfiguration = cell->measurement_timing_information; // sept. 2018
OCTET_STRING_fromBuf(&served_cell_information->measurementTimingConfiguration,
measurementTimingConfiguration,
strlen(measurementTimingConfiguration));
/* 4.1.2 gNB-DU System Information */
if (setup_req->cell[i].sys_info != NULL) {
asn1cCalloc(gnb_du_served_cells_item->gNB_DU_System_Information, gNB_DU_System_Information);
const f1ap_gnb_du_system_info_t *sys_info = setup_req->cell[i].sys_info;
AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n");
OCTET_STRING_fromBuf(&gNB_DU_System_Information->mIB_message, (const char *)sys_info->mib, sys_info->mib_length);
AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n");
OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length);
}
F1AP_GNB_DU_Served_Cells_Item_t *scell_item = &duServedCell->value.choice.GNB_DU_Served_Cells_Item;
scell_item->served_Cell_Information = encode_served_cell_info(cell);
scell_item->gNB_DU_System_Information = encode_system_info(sys_info);
}
/* mandatory */
@@ -534,7 +532,7 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3
gNB-DU Configuration Update
*/
int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_setup_req_t *f1ap_setup_req)
int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd)
{
F1AP_F1AP_PDU_t pdu= {0};
uint8_t *buffer=NULL;
@@ -546,227 +544,91 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_setup_req_t
initMsg->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate;
initMsg->criticality = F1AP_Criticality_reject;
initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate;
F1AP_GNBDUConfigurationUpdate_t *out = &pdu.choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate;
F1AP_GNBDUConfigurationUpdate_t *out = &initMsg->value.choice.GNBDUConfigurationUpdate;
/* mandatory */
/* c1. Transaction ID (integer value) */
asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie1);
asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie1);
ie1->id = F1AP_ProtocolIE_ID_id_TransactionID;
ie1->criticality = F1AP_Criticality_reject;
ie1->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_TransactionID;
ie1->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0);
ie1->value.choice.TransactionID = upd->transaction_id;
/* mandatory */
/* c2. Served_Cells_To_Add */
asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie2);
ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List;
ie2->criticality = F1AP_Criticality_reject;
ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List;
if (upd->num_cells_to_add > 0) {
AssertFatal(false, "code for adding cells not tested\n");
asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie2);
ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List;
ie2->criticality = F1AP_Criticality_reject;
ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List;
for (int j=0; j<1; j++) {
//
asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, F1AP_Served_Cells_To_Add_ItemIEs_t, served_cells_to_add_item_ies);
served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item;
served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject;
served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item;
F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item= &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item;
F1AP_Served_Cell_Information_t *served_cell_information=&served_cells_to_add_item->served_Cell_Information;
/* - nRCGI */
addnRCGI(served_cell_information->nRCGI, &f1ap_setup_req->cell[j].info);
/* - nRPCI */
/* 2.1.1 serverd cell Information */
f1ap_served_cell_info_t *cell = &f1ap_setup_req->cell[j].info;
served_cell_information->nRPCI = cell->nr_pci; // int 0..1007
/* - fiveGS_TAC */
if (cell->tac != NULL) {
uint32_t tac = htonl(*cell->tac);
served_cell_information->fiveGS_TAC = calloc(1, sizeof(*served_cell_information->fiveGS_TAC));
OCTET_STRING_fromBuf(served_cell_information->fiveGS_TAC, ((char *)&tac)+1, 3);
for (int j=0; j < upd->num_cells_to_add; j++) {
const f1ap_served_cell_info_t *cell = &upd->cell_to_add[j].info;
const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_add[j].sys_info;
asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, F1AP_Served_Cells_To_Add_ItemIEs_t, served_cells_to_add_item_ies);
served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item;
served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject;
served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item;
F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item= &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item;
served_cells_to_add_item->served_Cell_Information = encode_served_cell_info(cell);
served_cells_to_add_item->gNB_DU_System_Information = encode_system_info(sys_info);
}
/* - Configured_EPS_TAC */
if(1) {
served_cell_information->configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t));
OCTET_STRING_fromBuf(served_cell_information->configured_EPS_TAC,"2", 2);
}
asn1cSequenceAdd(served_cell_information->servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item);
MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity);
// // /* - CHOICE NR-MODE-Info */
F1AP_NR_Mode_Info_t *nR_Mode_Info=&served_cell_information->nR_Mode_Info;
LOG_E(F1AP,"Here hardcoded values instead of values from configuration file\n");
if (cell->mode == F1AP_MODE_FDD) {
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD;
/* > FDD >> FDD Info */
asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info);
/* >>> UL NRFreqInfo */
fDD_Info->uL_NRFreqInfo.nRARFCN = 999L;
asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, ul_freqBandNrItem);
ul_freqBandNrItem->freqBandIndicatorNr = 888L;
asn1cSequenceAdd(ul_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, ul_supportedSULFreqBandItem);
ul_supportedSULFreqBandItem->freqBandIndicatorNr = 777L;
/* >>> DL NRFreqInfo */
fDD_Info->dL_NRFreqInfo.nRARFCN = 666L;
asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, dl_freqBandNrItem);
dl_freqBandNrItem->freqBandIndicatorNr = 555L;
asn1cSequenceAdd(dl_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, dl_supportedSULFreqBandItem);
dl_supportedSULFreqBandItem->freqBandIndicatorNr = 444L;
/* >>> UL Transmission Bandwidth */
fDD_Info->uL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15;
fDD_Info->uL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11;
/* >>> DL Transmission Bandwidth */
fDD_Info->dL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15;
fDD_Info->dL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11;
} else if (cell->mode == F1AP_MODE_TDD) { // TDD
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD;
/* > TDD >> TDD Info */
asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info);
/* >>> ARFCN */
tDD_Info->nRFreqInfo.nRARFCN = 999L; // Integer
asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
nr_freqBandNrItem->freqBandIndicatorNr = 555L;
asn1cSequenceAdd(nr_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, nr_supportedSULFreqBandItem);
nr_supportedSULFreqBandItem->freqBandIndicatorNr = 444L;
tDD_Info->transmission_Bandwidth.nRSCS= F1AP_NRSCS_scs15;
tDD_Info->transmission_Bandwidth.nRNRB= F1AP_NRNRB_nrb11;
} else {
AssertFatal(false, "illegal mode %d\n", cell->mode);
}
/* - measurementTimingConfiguration */
char *measurementTimingConfiguration = "0"; // sept. 2018
OCTET_STRING_fromBuf(&served_cell_information->measurementTimingConfiguration,
measurementTimingConfiguration,
strlen(measurementTimingConfiguration));
/* 2.1.2 gNB-DU System Information */
asn1cCalloc(served_cells_to_add_item->gNB_DU_System_Information, gNB_DU_System_Information);
OCTET_STRING_fromBuf(&gNB_DU_System_Information->mIB_message, // sept. 2018
"1",
sizeof("1"));
OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, // sept. 2018
"1",
sizeof("1"));
}
/* mandatory */
/* c3. Served_Cells_To_Modify */
asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie3);
ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List;
ie3->criticality = F1AP_Criticality_reject;
ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List;
if (upd->num_cells_to_modify > 0) {
asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie3);
ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List;
ie3->criticality = F1AP_Criticality_reject;
ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List;
for (int i = 0; i < upd->num_cells_to_modify; i++) {
const f1ap_served_cell_info_t *cell = &upd->cell_to_modify[i].info;
const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_modify[i].sys_info;
asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, F1AP_Served_Cells_To_Modify_ItemIEs_t, served_cells_to_modify_item_ies);
served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item;
served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject;
served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item;
F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item=&served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item;
for (int i=0; i<1; i++) {
//
f1ap_served_cell_info_t *cell = &f1ap_setup_req->cell[i].info;
asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, F1AP_Served_Cells_To_Modify_ItemIEs_t, served_cells_to_modify_item_ies);
served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item;
served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject;
served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item;
F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item=&served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item;
/* 3.1 oldNRCGI */
//addnRGCI(served_cells_to_modify_item->oldNRCGI, f1ap_setup_req->cell[i]);
/* 3.2.1 serverd cell Information */
F1AP_Served_Cell_Information_t *served_cell_information= &served_cells_to_modify_item->served_Cell_Information;
/* - nRCGI */
//addnRGCI(served_cell_information->nRCGI,f1ap_setup_req->cell[i]);
/* - nRPCI */
served_cell_information->nRPCI = cell->nr_pci; // int 0..1007
/* - fiveGS_TAC */
asn1cCalloc(served_cell_information->fiveGS_TAC, tac );
OCTET_STRING_fromBuf(tac,
(const char *) &cell->tac,
3);
F1AP_NRCGI_t *oldNRCGI = &served_cells_to_modify_item->oldNRCGI;
const f1ap_plmn_t *old_plmn = &upd->cell_to_modify[i].old_plmn;
MCC_MNC_TO_PLMNID(old_plmn->mcc, old_plmn->mnc, old_plmn->mnc_digit_length, &oldNRCGI->pLMN_Identity);
NR_CELL_ID_TO_BIT_STRING(upd->cell_to_modify[i].old_nr_cellid, &oldNRCGI->nRCellIdentity);
/* - Configured_EPS_TAC */
if(1) {
asn1cCalloc(served_cell_information->configured_EPS_TAC, tmp2);
OCTET_STRING_fromBuf(tmp2,
"2",
2);
served_cells_to_modify_item->served_Cell_Information = encode_served_cell_info(cell);
served_cells_to_modify_item->gNB_DU_System_Information = encode_system_info(sys_info);
}
asn1cSequenceAdd(served_cell_information->servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item);
MCC_MNC_TO_PLMNID(cell->plmn.mcc, cell->plmn.mnc, cell->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity);
// // /* - CHOICE NR-MODE-Info */
F1AP_NR_Mode_Info_t *nR_Mode_Info= &served_cell_information->nR_Mode_Info;
if (cell->mode == F1AP_MODE_FDD) {
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD;
/* > FDD >> FDD Info */
asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info);
/* >>> UL NRFreqInfo */
fDD_Info->uL_NRFreqInfo.nRARFCN = 999L;
asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, ul_freqBandNrItem);
ul_freqBandNrItem->freqBandIndicatorNr = 888L;
asn1cSequenceAdd(ul_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, ul_supportedSULFreqBandItem);
ul_supportedSULFreqBandItem->freqBandIndicatorNr = 777L;
/* >>> DL NRFreqInfo */
fDD_Info->dL_NRFreqInfo.nRARFCN = 666L;
asn1cSequenceAdd(dl_freqBandNrItem->supportedSULBandList.list, F1AP_FreqBandNrItem_t, dl_freqBandNrItem);
dl_freqBandNrItem->freqBandIndicatorNr = 555L;
F1AP_SupportedSULFreqBandItem_t dl_supportedSULFreqBandItem;
memset((void *)&dl_supportedSULFreqBandItem, 0, sizeof(F1AP_SupportedSULFreqBandItem_t));
dl_supportedSULFreqBandItem.freqBandIndicatorNr = 444L;
/* >>> UL Transmission Bandwidth */
fDD_Info->uL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15;
fDD_Info->uL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11;
/* >>> DL Transmission Bandwidth */
fDD_Info->dL_Transmission_Bandwidth.nRSCS = F1AP_NRSCS_scs15;
fDD_Info->dL_Transmission_Bandwidth.nRNRB = F1AP_NRNRB_nrb11;
} else if (cell->mode == F1AP_MODE_TDD) { // TDD
nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD;
/* > TDD >> TDD Info */
asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info);
/* >>> ARFCN */
tDD_Info->nRFreqInfo.nRARFCN = 999L; // Integer
asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem);
nr_freqBandNrItem->freqBandIndicatorNr = 555L;
asn1cSequenceAdd(nr_freqBandNrItem->supportedSULBandList.list, F1AP_SupportedSULFreqBandItem_t, nr_supportedSULFreqBandItem);
nr_supportedSULFreqBandItem->freqBandIndicatorNr = 444L;
tDD_Info->transmission_Bandwidth.nRSCS= F1AP_NRSCS_scs15;
tDD_Info->transmission_Bandwidth.nRNRB= F1AP_NRNRB_nrb11;
} else {
AssertFatal(false, "unknown mode %d\n", cell->mode);
}
/* - measurementTimingConfiguration */
char *measurementTimingConfiguration = "0"; // sept. 2018
OCTET_STRING_fromBuf(&served_cell_information->measurementTimingConfiguration,
measurementTimingConfiguration,
strlen(measurementTimingConfiguration));
/* 3.2.2 gNB-DU System Information */
asn1cCalloc( served_cells_to_modify_item->gNB_DU_System_Information, gNB_DU_System_Information);
OCTET_STRING_fromBuf(&gNB_DU_System_Information->mIB_message, // sept. 2018
"1",
sizeof("1"));
OCTET_STRING_fromBuf(&gNB_DU_System_Information->sIB1_message, // sept. 2018
"1",
sizeof("1"));
}
/* mandatory */
/* c4. Served_Cells_To_Delete */
asn1cSequenceAdd(out, F1AP_GNBDUConfigurationUpdateIEs_t, ie4);
ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List;
ie4->criticality = F1AP_Criticality_reject;
ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List;
for (int i=0; i<1; i++) {
//
asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, F1AP_Served_Cells_To_Delete_ItemIEs_t, served_cells_to_delete_item_ies);
served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item;
served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject;
served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item;
F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item=&served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item;
/* 3.1 oldNRCGI */
addnRCGI(served_cells_to_delete_item->oldNRCGI, &f1ap_setup_req->cell[i].info);
if (upd->num_cells_to_delete > 0) {
asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie4);
ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List;
ie4->criticality = F1AP_Criticality_reject;
ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List;
AssertFatal(upd->num_cells_to_delete == 0, "code for deleting cells not tested\n");
for (int i=0; i<upd->num_cells_to_delete; i++) {
asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, F1AP_Served_Cells_To_Delete_ItemIEs_t, served_cells_to_delete_item_ies);
served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item;
served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject;
served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item;
F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item=&served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item;
addnRCGI(served_cells_to_delete_item->oldNRCGI, &upd->cell_to_delete[i]);
}
}
AssertFatal(upd->gNB_DU_ID == 0, "encoding of gNB-DU Id not handled yet\n");
if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) {
LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n");
return -1;
}
ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu);
f1ap_itti_send_sctp_data_req(assoc_id, buffer, len);
return 0;
}

View File

@@ -50,7 +50,7 @@ int DU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint3
/*
* F1 Setup
*/
int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_setup_req_t *setup_req);
int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setup_req);
int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
@@ -59,8 +59,7 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3
/*
* gNB-DU Configuration Update
*/
int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id,
f1ap_setup_req_t *f1ap_du_data);
int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd);
int DU_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);

View File

@@ -34,9 +34,10 @@
#ifndef F1AP_DU_RRC_MESSAGE_TRANSFER_H_
#define F1AP_DU_RRC_MESSAGE_TRANSFER_H_
#include "f1ap_common.h"
#include <openair2/RRC/NR/MESSAGES/asn1_msg.h>
int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu);
struct F1AP_F1AP_PDU;
int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, struct F1AP_F1AP_PDU *pdu);
int DU_send_UL_NR_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_ul_rrc_message_t *msg);

View File

@@ -170,6 +170,10 @@ void *F1AP_DU_task(void *arg) {
DU_send_UE_CONTEXT_MODIFICATION_REQUIRED(assoc_id, &F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(msg));
break;
case F1AP_GNB_DU_CONFIGURATION_UPDATE:
DU_send_gNB_DU_CONFIGURATION_UPDATE(assoc_id, &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg));
break;
case TERMINATE_MESSAGE:
LOG_W(F1AP, " *** Exiting F1AP thread\n");
itti_exit_task();

View File

@@ -40,24 +40,6 @@
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
bool DURecvCb(protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_sizeP,
unsigned char *const sdu_buffer_pP,
const pdcp_transmission_mode_t modeP,
const uint32_t *sourceL2Id,
const uint32_t *destinationL2Id)
{
// The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue
uint8_t *sdu = malloc16(sdu_buffer_sizeP);
memcpy(sdu, sdu_buffer_pP, sdu_buffer_sizeP);
du_rlc_data_req(ctxt_pP, srb_flagP, false, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu);
return true;
}
int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
{
F1AP_UEContextSetupRequest_t *container;
@@ -305,6 +287,7 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
ie7->criticality = F1AP_Criticality_ignore;
ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List;
for (int i=0; i< resp->drbs_to_be_setup_length; i++) {
f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i];
//
asn1cSequenceAdd(ie7->value.choice.DRBs_Setup_List.list,
F1AP_DRBs_Setup_ItemIEs_t, drbs_setup_item_ies);
@@ -315,14 +298,17 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
/* ADD */
F1AP_DRBs_Setup_Item_t *drbs_setup_item=&drbs_setup_item_ies->value.choice.DRBs_Setup_Item;
/* dRBID */
drbs_setup_item->dRBID = resp->drbs_to_be_setup[i].drb_id;
drbs_setup_item->dRBID = drb->drb_id;
/* OPTIONAL */
/* lCID */
//drbs_setup_item.lCID = (F1AP_LCID_t *)calloc(1, sizeof(F1AP_LCID_t));
//drbs_setup_item.lCID = 1L;
for (int j=0; j<resp->drbs_to_be_setup[i].up_dl_tnl_length; j++) {
for (int j=0; j<drb->up_dl_tnl_length; j++) {
const f1ap_up_tnl_t *tnl = &drb->up_dl_tnl[j];
DevAssert(tnl->teid > 0);
/* ADD */
asn1cSequenceAdd(drbs_setup_item->dLUPTNLInformation_ToBeSetup_List.list,
F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item);
@@ -330,12 +316,9 @@ int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_set
/* gTPTunnel */
asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel);
/* transportLayerAddress */
struct sockaddr_in addr= {0};
inet_pton(AF_INET, getCxt(0)->net_config.DU_f1_ip_address.ipv4_address, &addr.sin_addr.s_addr);
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr,
&gTPTunnel->transportLayerAddress);
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress);
/* gTP_TEID */
INT32_TO_OCTET_STRING(resp->drbs_to_be_setup[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID);
INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID);
} // for j
} // for i
@@ -1008,7 +991,6 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t
DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item);
DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item);
f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID;
newGtpuDeleteOneTunnel(0, f1ap_ue_context_modification_req->gNB_DU_ue_id, f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id);
}
}
@@ -1166,20 +1148,8 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_cont
drbs_setupmod_item->dRBID = resp->drbs_to_be_setup[i].drb_id;
for (int j=0; j<resp->drbs_to_be_setup[i].up_dl_tnl_length; j++) {
f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i];
transport_layer_addr_t tl_addr = {0};
memcpy(tl_addr.buffer, &drb->up_ul_tnl[0].tl_address, sizeof(drb->up_ul_tnl[0].tl_address));
tl_addr.length = sizeof(drb->up_ul_tnl[0].tl_address) * 8;
drb->up_dl_tnl[j].teid = newGtpuCreateTunnel(getCxt(0)->gtpInst,
resp->gNB_DU_ue_id,
drb->drb_id,
drb->drb_id,
drb->up_ul_tnl[j].teid,
-1, // no qfi
tl_addr,
drb->up_ul_tnl[0].port,
DURecvCb,
NULL);
const f1ap_up_tnl_t *tnl = &resp->drbs_to_be_setup[i].up_dl_tnl[j];
DevAssert(tnl->teid > 0);
/* ADD */
asn1cSequenceAdd(drbs_setupmod_item->dLUPTNLInformation_ToBeSetup_List.list,
@@ -1188,12 +1158,9 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_cont
/* gTPTunnel */
asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel);
/* transportLayerAddress */
struct sockaddr_in addr= {0};
inet_pton(AF_INET, getCxt(0)->net_config.DU_f1_ip_address.ipv4_address, &addr.sin_addr.s_addr);
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr,
&gTPTunnel->transportLayerAddress);
TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress);
/* gTP_TEID */
INT32_TO_OCTET_STRING(resp->drbs_to_be_setup[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID);
INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID);
} // for j
} // for i
}

View File

@@ -45,7 +45,7 @@ static const f1ap_message_processing_t f1ap_messages_processing[][3] = {
{0, 0, 0}, /* Reset */
{CU_handle_F1_SETUP_REQUEST, DU_handle_F1_SETUP_RESPONSE, DU_handle_F1_SETUP_FAILURE}, /* F1Setup */
{0, 0, 0}, /* ErrorIndication */
{0, 0, 0}, /* gNBDUConfigurationUpdate */
{CU_handle_gNB_DU_CONFIGURATION_UPDATE, 0, 0}, /* gNBDUConfigurationUpdate */
{DU_handle_gNB_CU_CONFIGURATION_UPDATE,
CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE,
CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE}, /* gNBCUConfigurationUpdate */

View File

@@ -37,8 +37,8 @@ static pthread_mutex_t cu2du_mutex = PTHREAD_MUTEX_INITIALIZER;
void cu_init_f1_ue_data(void)
{
pthread_mutex_lock(&cu2du_mutex);
DevAssert(cu2du_ue_mapping == NULL);
cu2du_ue_mapping = hashtable_create(1319, NULL, free); // 1319 is prime, default hash func (unit), free()
if (cu2du_ue_mapping == NULL) // hack: there is nothing to free this properly
cu2du_ue_mapping = hashtable_create(1319, NULL, free); // 1319 is prime, default hash func (unit), free()
DevAssert(cu2du_ue_mapping != NULL);
pthread_mutex_unlock(&cu2du_mutex);
}

View File

@@ -1097,13 +1097,74 @@ static int read_du_cell_info(configmodule_interface_t *cfg,
info->plmn.mnc_digit_length);
info->nr_cellid = (uint64_t) * (GNBParamList.paramarray[0][GNB_NRCELLID_IDX].u64ptr);
LOG_W(GNB_APP, "no slices transported via F1 Setup Request!\n");
info->num_ssi = 0;
info->num_ssi = 1;
paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC;
checkedparam_t config_check_SNSSAIParams[] = SNSSAIPARAMS_CHECK;
for (int J = 0; J < sizeof(SNSSAIParams) / sizeof(paramdef_t); ++J)
SNSSAIParams[J].chkPptr = &(config_check_SNSSAIParams[J]);
paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
char snssaistr[MAX_OPTNAME_SIZE * 2 + 8];
sprintf(snssaistr, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_PLMN_LIST, 0);
config_getlist(config_get_if(), &SNSSAIParamList, SNSSAIParams, sizeof(SNSSAIParams) / sizeof(paramdef_t), snssaistr);
AssertFatal(SNSSAIParamList.numelt == 1, "cannot handle no NSSAI or more than 1\n");
info->sst = *SNSSAIParamList.paramarray[0][GNB_SLICE_SERVICE_TYPE_IDX].uptr;
info->sd = *SNSSAIParamList.paramarray[0][GNB_SLICE_DIFFERENTIATOR_IDX].uptr;
return 1;
}
static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
f1ap_tdd_info_t read_tdd_config(const NR_ServingCellConfigCommon_t *scc)
{
const NR_FrequencyInfoDL_t *dl = scc->downlinkConfigCommon->frequencyInfoDL;
f1ap_tdd_info_t tdd = {
.freqinfo.arfcn = dl->absoluteFrequencyPointA,
.freqinfo.band = *dl->frequencyBandList.list.array[0],
.tbw.scs = dl->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
.tbw.nrb = dl->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,
};
return tdd;
}
static f1ap_fdd_info_t read_fdd_config(const NR_ServingCellConfigCommon_t *scc)
{
const NR_FrequencyInfoDL_t *dl = scc->downlinkConfigCommon->frequencyInfoDL;
const NR_FrequencyInfoUL_t *ul = scc->uplinkConfigCommon->frequencyInfoUL;
f1ap_fdd_info_t fdd = {
.dl_freqinfo.arfcn = dl->absoluteFrequencyPointA,
.ul_freqinfo.arfcn = *ul->absoluteFrequencyPointA,
.dl_tbw.scs = dl->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
.ul_tbw.scs = ul->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
.dl_tbw.nrb = dl->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,
.ul_tbw.nrb = ul->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,
.dl_freqinfo.band = *dl->frequencyBandList.list.array[0],
.ul_freqinfo.band = *ul->frequencyBandList->list.array[0],
};
return fdd;
}
f1ap_gnb_du_system_info_t *get_sys_info(NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1)
{
int buf_len = 3;
f1ap_gnb_du_system_info_t *sys_info = calloc(1, sizeof(*sys_info));
AssertFatal(sys_info != NULL, "out of memory\n");
sys_info->mib = calloc(buf_len, sizeof(*sys_info->mib));
DevAssert(sys_info->mib != NULL);
DevAssert(mib != NULL);
sys_info->mib_length = encode_MIB_NR(mib, 0, sys_info->mib, buf_len);
DevAssert(sys_info->mib_length == buf_len);
DevAssert(sib1 != NULL);
NR_SIB1_t *bcch_SIB1 = sib1->message.choice.c1->choice.systemInformationBlockType1;
sys_info->sib1 = calloc(NR_MAX_SIB_LENGTH / 8, sizeof(*sys_info->sib1));
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_SIB1, NULL, (void *)bcch_SIB1, sys_info->sib1, NR_MAX_SIB_LENGTH / 8);
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
sys_info->sib1_length = (enc_rval.encoded + 7) / 8;
return sys_info;
}
f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
const char *name,
const f1ap_served_cell_info_t *info,
const NR_ServingCellConfigCommon_t *scc,
@@ -1128,27 +1189,14 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
req->cell[0].info.nr_cellid);
req->cell[0].info.nr_pci = *scc->physCellId;
struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
if (scc->tdd_UL_DL_ConfigurationCommon) {
LOG_I(GNB_APP, "ngran_DU: Configuring Cell %d for TDD\n", 0);
req->cell[0].info.mode = F1AP_MODE_TDD;
f1ap_tdd_info_t *tdd = &req->cell[0].info.tdd;
tdd->freqinfo.arfcn = frequencyInfoDL->absoluteFrequencyPointA;
tdd->tbw.scs = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
tdd->tbw.nrb = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
tdd->freqinfo.band = *frequencyInfoDL->frequencyBandList.list.array[0];
req->cell[0].info.tdd = read_tdd_config(scc);
} else {
LOG_I(GNB_APP, "ngran_DU: Configuring Cell %d for FDD\n", 0);
req->cell[0].info.mode = F1AP_MODE_FDD;
f1ap_fdd_info_t *fdd = &req->cell[0].info.fdd;
fdd->dl_freqinfo.arfcn = frequencyInfoDL->absoluteFrequencyPointA;
fdd->ul_freqinfo.arfcn = *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA;
fdd->dl_tbw.scs = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
fdd->ul_tbw.scs = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
fdd->dl_tbw.nrb = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
fdd->ul_tbw.nrb = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
fdd->dl_freqinfo.band = *frequencyInfoDL->frequencyBandList.list.array[0];
fdd->ul_freqinfo.band = *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0];
req->cell[0].info.fdd = read_fdd_config(scc);
}
req->cell[0].info.measurement_timing_information = "0";
@@ -1157,22 +1205,7 @@ static f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
// in NSA we don't transmit SIB1, so cannot fill DU system information
// so cannot send MIB either
int buf_len = 3; // this is what we assume in monolithic
req->cell[0].sys_info = calloc(1, sizeof(*req->cell[0].sys_info));
AssertFatal(req->cell[0].sys_info != NULL, "out of memory\n");
f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info;
sys_info->mib = calloc(buf_len, sizeof(*sys_info->mib));
DevAssert(sys_info->mib != NULL);
DevAssert(mib != NULL);
sys_info->mib_length = encode_MIB_NR(mib, 0, sys_info->mib, buf_len);
DevAssert(sys_info->mib_length == buf_len);
DevAssert(sib1 != NULL);
NR_SIB1_t *bcch_SIB1 = sib1->message.choice.c1->choice.systemInformationBlockType1;
sys_info->sib1 = calloc(NR_MAX_SIB_LENGTH / 8, sizeof(*sys_info->sib1));
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_SIB1, NULL, (void *)bcch_SIB1, sys_info->sib1, NR_MAX_SIB_LENGTH / 8);
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
sys_info->sib1_length = (enc_rval.encoded + 7) / 8;
req->cell[0].sys_info = get_sys_info(mib, sib1);
}
int num = read_version(TO_STRING(NR_RRC_VERSION), &req->rrc_ver[0], &req->rrc_ver[1], &req->rrc_ver[2]);
@@ -1569,7 +1602,6 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
sprintf(aprefix,"%s.[%u].%s",GNB_CONFIG_STRING_GNB_LIST,i,GNB_CONFIG_STRING_SCTP_CONFIG);
config_get(config_get_if(), SCTPParams, sizeofArray(SCTPParams), aprefix);
LOG_I(GNB_APP,"F1AP: gNB_CU_id[%d] %d\n",k,rrc->node_id);
rrc->node_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr));
LOG_I(GNB_APP,"F1AP: gNB_CU_name[%d] %s\n",k,rrc->node_name);
rrc->eth_params_s.local_if_name = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_IF_NAME_IDX].strptr));
rrc->eth_params_s.my_addr = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_ADDRESS_IDX].strptr));
@@ -1583,6 +1615,7 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
rrc->node_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr));
rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr);
if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_mac") == 0) {
@@ -1644,6 +1677,17 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc)
AssertFatal((nrrrc_config.mnc_digit_length[l] == 2) ||
(nrrrc_config.mnc_digit_length[l] == 3),"BAD MNC DIGIT LENGTH %d",
nrrrc_config.mnc_digit_length[l]);
paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC;
checkedparam_t config_check_SNSSAIParams[] = SNSSAIPARAMS_CHECK;
for (int J = 0; J < sizeof(SNSSAIParams) / sizeof(paramdef_t); ++J)
SNSSAIParams[J].chkPptr = &(config_check_SNSSAIParams[J]);
paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
char snssaistr[MAX_OPTNAME_SIZE * 2 + 8];
sprintf(snssaistr, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_PLMN_LIST, l);
config_getlist(config_get_if(), &SNSSAIParamList, SNSSAIParams, sizeof(SNSSAIParams) / sizeof(paramdef_t), snssaistr);
AssertFatal(SNSSAIParamList.numelt == 1, "cannot handle no NSSAI or more than 1\n");
nrrrc_config.sst = *SNSSAIParamList.paramarray[0][GNB_SLICE_SERVICE_TYPE_IDX].uptr;
nrrrc_config.sd = *SNSSAIParamList.paramarray[0][GNB_SLICE_DIFFERENTIATOR_IDX].uptr;
}
nrrrc_config.enable_sdap = *GNBParamList.paramarray[i][GNB_ENABLE_SDAP_IDX].iptr;
LOG_I(GNB_APP, "SDAP layer is %s\n", nrrrc_config.enable_sdap ? "enabled" : "disabled");

View File

@@ -106,6 +106,12 @@ void RCconfig_NRRRC(gNB_RRC_INST *rrc);
int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i);
int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i);
void wait_f1_setup_response(void);
f1ap_setup_req_t *RC_read_F1Setup(uint64_t id,
const char *name,
const f1ap_served_cell_info_t *info,
const NR_ServingCellConfigCommon_t *scc,
NR_BCCH_BCH_Message_t *mib,
const NR_BCCH_DL_SCH_Message_t *sib1);
int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update);
MessageDef *RCconfig_NR_CU_E1(const E1_t *entity);
ngran_node_t get_node_type(void);

View File

@@ -1683,7 +1683,8 @@ static void nr_generate_Msg4(module_id_t module_idP,
NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti);
if (!UE) {
LOG_E(NR_MAC, "want to generate Msg4, but rnti %04x not in the table\n", ra->rnti);
LOG_E(NR_MAC, "want to generate Msg4, but rnti %04x not found. Abort RA\n", ra->rnti);
nr_clear_ra_proc(0, 0, frameP, ra);
return;
}
@@ -1936,7 +1937,7 @@ static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, s
LOG_A(NR_MAC, "(UE RNTI 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", ra->rnti);
} else {
LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at Msg4!\n", frame, slot, ra->rnti);
nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs);
nr_mac_trigger_ul_failure(UE->rnti);
}
// Pause scheduling according to:

View File

@@ -936,6 +936,9 @@ void nr_schedule_ue_spec(module_id_t module_id,
NR_UEs_t *UE_info = &gNB_mac->UE_info;
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE);
UE_iterator(UE_info->list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
@@ -1237,6 +1240,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock, TBS));
UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize;
gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
} else { /* initial transmission */
LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot);
uint8_t *buf = (uint8_t *) harq->transportBlock;
@@ -1353,6 +1357,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
UE->mac_stats.dl.num_mac_sdu += sdus;
UE->mac_stats.dl.current_rbs = sched_pdsch->rbSize;
UE->mac_stats.dl.total_sdu_bytes += dlsch_total_bytes;
gNB_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
/* save retransmission information */
harq->sched_pdsch = *sched_pdsch;

View File

@@ -3064,15 +3064,22 @@ bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti)
return sched_ctrl->release_timer == 0;
}
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing)
void nr_mac_trigger_ul_failure(int rnti)
{
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti);
if (UE == NULL) {
LOG_E(NR_MAC, "could not find UE RNTI %04x\n", rnti);
return;
}
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (sched_ctrl->ul_failure) {
/* already running */
return;
}
sched_ctrl->ul_failure = true;
// 30 seconds till triggering release request
sched_ctrl->ul_failure_timer = 30000 << subcarrier_spacing;
NR_SubcarrierSpacing_t subcarrier_spacing = UE->current_DL_BWP.scs;
sched_ctrl->ul_failure_timer = 5000 << subcarrier_spacing;
}
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl)
@@ -3097,7 +3104,7 @@ void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ct
.gNB_CU_ue_id = ue_data.secondary_ue,
.gNB_DU_ue_id = rnti,
.cause = F1AP_CAUSE_RADIO_NETWORK,
.cause_value = F1AP_CauseRadioNetwork_rl_failure_others,
.cause_value = F1AP_CauseRadioNetwork_rl_failure_rlc,
};
nrmac->mac_rrc.ue_context_release_request(&request);
}

View File

@@ -680,7 +680,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
"UE %04x: Detected UL Failure on PUSCH after %d PUSCH DTX, stopping scheduling\n",
UE->rnti,
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt);
nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
nr_mac_trigger_ul_failure(UE->rnti);
}
}
} else if(sduP) {

View File

@@ -442,7 +442,7 @@ void nr_mac_trigger_release_timer(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierS
bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti);
void nr_mac_release_ue(gNB_MAC_INST *mac, int rnti);
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing);
void nr_mac_trigger_ul_failure(int rnti);
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl);
void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl);

View File

@@ -23,8 +23,11 @@
#include "mac_proto.h"
#include "openair2/F1AP/f1ap_ids.h"
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "F1AP_CauseRadioNetwork.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
@@ -34,6 +37,59 @@ const uint64_t qos_fiveqi[26] = {1, 2, 3, 4, 65, 66, 67, 71, 72, 73, 74, 76, 5,
const uint64_t qos_priority[26] = {20, 40, 30, 50, 7, 20, 15, 56, 56, 56, 56, 56, 10,
60, 70, 80, 90, 5, 55, 65, 68, 19, 22, 24, 21, 18};
static instance_t get_f1_gtp_instance(void)
{
const f1ap_cudu_inst_t *inst = getCxt(0);
if (!inst)
return -1; // means no F1
return inst->gtpInst;
}
static int drb_gtpu_create(instance_t instance,
uint32_t ue_id,
int incoming_id,
int outgoing_id,
int qfi,
in_addr_t tlAddress, // only IPv4 now
teid_t outgoing_teid,
gtpCallback callBack,
gtpCallbackSDAP callBackSDAP,
gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp)
{
gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0};
create_tunnel_req.incoming_rb_id[0] = incoming_id;
create_tunnel_req.pdusession_id[0] = outgoing_id;
memcpy(&create_tunnel_req.dst_addr[0].buffer, &tlAddress, sizeof(uint8_t) * 4);
create_tunnel_req.dst_addr[0].length = 32;
create_tunnel_req.outgoing_teid[0] = outgoing_teid;
create_tunnel_req.outgoing_qfi[0] = qfi;
create_tunnel_req.num_tunnels = 1;
create_tunnel_req.ue_id = ue_id;
// we use gtpv1u_create_ngu_tunnel because it returns the interface
// address and port of the interface; apart from that, we also might call
// newGtpuCreateTunnel() directly
return gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, callBack, callBackSDAP);
}
bool DURecvCb(protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_sizeP,
unsigned char *const sdu_buffer_pP,
const pdcp_transmission_mode_t modeP,
const uint32_t *sourceL2Id,
const uint32_t *destinationL2Id)
{
// The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue
uint8_t *sdu = malloc16(sdu_buffer_sizeP);
memcpy(sdu, sdu_buffer_pP, sdu_buffer_sizeP);
du_rlc_data_req(ctxt_pP, srb_flagP, false, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu);
return true;
}
static long get_lcid_from_drbid(int drb_id)
{
return drb_id + 3; /* LCID is DRB + 3 */
@@ -88,6 +144,12 @@ void f1_setup_failure(const f1ap_setup_failure_t *failure)
exit(1);
}
void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack)
{
(void) ack;
LOG_I(MAC, "received gNB-DU configuration update acknowledge\n");
}
static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb)
{
long priority = srb->srb_id; // high priority for SRB
@@ -133,6 +195,7 @@ static int handle_ue_context_drbs_setup(int rnti,
NR_CellGroupConfig_t *cellGroupConfig)
{
DevAssert(req_drbs != NULL && resp_drbs != NULL && cellGroupConfig != NULL);
instance_t f1inst = get_f1_gtp_instance();
/* Note: the actual GTP tunnels are created in the F1AP breanch of
* ue_context_*_response() */
@@ -140,12 +203,32 @@ static int handle_ue_context_drbs_setup(int rnti,
AssertFatal(*resp_drbs != NULL, "out of memory\n");
for (int i = 0; i < drbs_len; i++) {
const f1ap_drb_to_be_setup_t *drb = &req_drbs[i];
f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i];
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb);
nr_rlc_add_drb(rnti, drb->drb_id, rlc_BearerConfig);
(*resp_drbs)[i] = *drb;
*resp_drb = *drb;
// just put same number of tunnels in DL as in UL
(*resp_drbs)[i].up_dl_tnl_length = drb->up_ul_tnl_length;
DevAssert(drb->up_ul_tnl_length == 1);
resp_drb->up_dl_tnl_length = drb->up_ul_tnl_length;
if (f1inst >= 0) { // we actually use F1-U
int qfi = -1; // don't put PDU session marker in GTP
gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0};
int ret = drb_gtpu_create(f1inst,
rnti,
drb->drb_id,
drb->drb_id,
qfi,
drb->up_ul_tnl[0].tl_address,
drb->up_ul_tnl[0].teid,
DURecvCb,
NULL,
&resp_f1);
AssertFatal(ret >= 0, "Unable to create GTP Tunnel for F1-U\n");
memcpy(&resp_drb->up_dl_tnl[0].tl_address, &resp_f1.gnb_addr.buffer, 4);
resp_drb->up_dl_tnl[0].teid = resp_f1.gnb_NGu_teid[0];
}
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
DevAssert(ret == 0);
@@ -159,6 +242,7 @@ static int handle_ue_context_drbs_release(int rnti,
NR_CellGroupConfig_t *cellGroupConfig)
{
DevAssert(req_drbs != NULL && cellGroupConfig != NULL);
instance_t f1inst = get_f1_gtp_instance();
cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList));
AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n");
@@ -178,6 +262,8 @@ static int handle_ue_context_drbs_release(int rnti,
}
if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) {
nr_rlc_release_entity(rnti, lcid);
if (f1inst >= 0)
newGtpuDeleteOneTunnel(f1inst, rnti, drb->rb_id);
asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1);
long *plcid = malloc(sizeof(*plcid));
AssertFatal(plcid != NULL, "out of memory\n");
@@ -552,6 +638,10 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd)
return;
}
instance_t f1inst = get_f1_gtp_instance();
if (f1inst >= 0)
newGtpuDeleteAllTunnels(f1inst, cmd->gNB_DU_ue_id);
if (UE->UE_sched_ctrl.ul_failure || cmd->rrc_container_length == 0) {
/* The UE is already not connected anymore or we have nothing to forward*/
nr_mac_release_ue(mac, cmd->gNB_DU_ue_id);

View File

@@ -28,6 +28,7 @@
void f1_setup_response(const f1ap_setup_resp_t *resp);
void f1_setup_failure(const f1ap_setup_failure_t *failure);
void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack);
NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig);
void ue_context_setup_request(const f1ap_ue_context_setup_t *req);
void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req);

View File

@@ -26,6 +26,7 @@
#include "f1ap_messages_types.h"
typedef void (*f1_setup_request_func_t)(const f1ap_setup_req_t* req);
typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_update_t *upd);
typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp);
typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req,

View File

@@ -66,6 +66,51 @@ static void f1_setup_request_direct(const f1ap_setup_req_t *req)
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
}
static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_update_t *upd)
{
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE);
msg->ittiMsgHeader.originInstance = -1; // means monolithic
f1ap_gnb_du_configuration_update_t *f1ap_msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg);
DevAssert(upd->gNB_DU_ID == NULL);
f1ap_msg->transaction_id = upd->transaction_id;
DevAssert(upd->num_cells_to_add == 0);
DevAssert(upd->num_cells_to_delete == 0);
f1ap_msg->num_cells_to_modify = upd->num_cells_to_modify;
for (int n = 0; n < upd->num_cells_to_modify; ++n) {
f1ap_msg->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid;
f1ap_msg->cell_to_modify[n].info = upd->cell_to_modify[n].info; // copy most fields
if (upd->cell_to_modify[n].info.tac) {
f1ap_msg->cell_to_modify[n].info.tac = malloc(sizeof(*f1ap_msg->cell_to_modify[n].info.tac));
AssertFatal(f1ap_msg->cell_to_modify[n].info.tac != NULL, "out of memory\n");
*f1ap_msg->cell_to_modify[n].info.tac = *upd->cell_to_modify[n].info.tac;
}
if (upd->cell_to_modify[n].info.measurement_timing_information)
f1ap_msg->cell_to_modify[n].info.measurement_timing_information = strdup(upd->cell_to_modify[n].info.measurement_timing_information);
if (upd->cell_to_modify[n].sys_info) {
f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info;
f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info));
AssertFatal(copy_sys_info != NULL, "out of memory\n");
f1ap_msg->cell_to_modify[n].sys_info = copy_sys_info;
copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t));
AssertFatal(copy_sys_info->mib != NULL, "out of memory\n");
memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length);
copy_sys_info->mib_length = orig_sys_info->mib_length;
if (orig_sys_info->sib1_length > 0) {
copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t));
AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n");
memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length);
copy_sys_info->sib1_length = orig_sys_info->sib1_length;
}
}
}
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
}
static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp)
{
DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length);
@@ -227,6 +272,7 @@ static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const
void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
{
mac_rrc->f1_setup_request = f1_setup_request_direct;
mac_rrc->gnb_du_configuration_update = gnb_du_configuration_update_direct;
mac_rrc->ue_context_setup_response = ue_context_setup_response_direct;
mac_rrc->ue_context_modification_response = ue_context_modification_response_direct;
mac_rrc->ue_context_modification_required = ue_context_modification_required_direct;

View File

@@ -100,6 +100,39 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req)
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
}
static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_update_t *upd)
{
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE);
f1ap_gnb_du_configuration_update_t *f1_upd = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg);
f1_upd->transaction_id = upd->transaction_id;
AssertFatal(upd->num_cells_to_add == 0, "gNB-DU config update: cells to add not supported\n");
f1_upd->num_cells_to_modify = upd->num_cells_to_modify;
for (int n = 0; n < upd->num_cells_to_modify; ++n) {
f1_upd->cell_to_modify[n].old_plmn = upd->cell_to_modify[n].old_plmn;
f1_upd->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid;
f1_upd->cell_to_modify[n].info = upd->cell_to_modify[n].info;
if (upd->cell_to_modify[n].sys_info) {
f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info;
f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info));
f1_upd->cell_to_modify[n].sys_info = copy_sys_info;
copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t));
AssertFatal(copy_sys_info->mib != NULL, "out of memory\n");
memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length);
copy_sys_info->mib_length = orig_sys_info->mib_length;
if (orig_sys_info->sib1_length > 0) {
copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t));
AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n");
memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length);
copy_sys_info->sib1_length = orig_sys_info->sib1_length;
}
}
}
AssertFatal(upd->num_cells_to_delete == 0, "gNB-DU config update: cells to add not supported\n");
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
}
static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp)
{
DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length);
@@ -239,6 +272,7 @@ static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1
void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
{
mac_rrc->f1_setup_request = f1_setup_request_f1ap;
mac_rrc->gnb_du_configuration_update = gnb_du_configuration_update_f1ap;
mac_rrc->ue_context_setup_response = ue_context_setup_response_f1ap;
mac_rrc->ue_context_modification_response = ue_context_modification_response_f1ap;
mac_rrc->ue_context_modification_required = ue_context_modification_required_f1ap;

View File

@@ -684,6 +684,7 @@ typedef struct NR_bler_options {
typedef struct nr_mac_rrc_ul_if_s {
f1_setup_request_func_t f1_setup_request;
gnb_du_configuration_update_t gnb_du_configuration_update;
ue_context_setup_response_func_t ue_context_setup_response;
ue_context_modification_response_func_t ue_context_modification_response;
ue_context_modification_required_func_t ue_context_modification_required;
@@ -743,6 +744,11 @@ typedef struct f1_config_t {
uint32_t gnb_id; // associated gNB's ID, not used in DU itself
} f1_config_t;
typedef struct {
uint64_t total_prb_aggregate;
uint64_t used_prb_aggregate;
} mac_stats_t;
/*! \brief top level eNB MAC structure */
typedef struct gNB_MAC_INST_s {
/// Ethernet parameters for northbound midhaul interface
@@ -862,6 +868,8 @@ typedef struct gNB_MAC_INST_s {
pthread_mutex_t sched_lock;
mac_stats_t mac_stats;
} gNB_MAC_INST;
#endif /*__LAYER2_NR_MAC_GNB_H__ */

View File

@@ -569,6 +569,7 @@ rb_found:
#endif
}
extern void nr_mac_trigger_ul_failure(int rnti);
static void max_retx_reached(void *_ue, nr_rlc_entity_t *entity)
{
nr_rlc_ue_t *ue = _ue;
@@ -615,15 +616,7 @@ rb_found:
if (!is_enb)
return;
#if 0
msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION);
RLC_SDU_INDICATION(msg).rnti = ue->rnti;
RLC_SDU_INDICATION(msg).is_successful = 0;
RLC_SDU_INDICATION(msg).srb_id = rb_id;
RLC_SDU_INDICATION(msg).message_id = -1;
/* TODO: accept more than 1 instance? here we send to instance id 0 */
itti_send_msg_to_task(TASK_RRC_ENB, 0, msg);
#endif
nr_mac_trigger_ul_failure(ue->rnti);
}
void nr_rlc_reestablish_entity(int rnti, int lc_id)

View File

@@ -55,17 +55,7 @@ static bool resp_freelist_inited = false;
void init_sched_response(void)
{
/* init only once */
if (pthread_mutex_lock(&resp_mutex))
AssertFatal(0, "pthread_mutex_lock failed\n");
if (resp_freelist_inited) {
if (pthread_mutex_unlock(&resp_mutex))
AssertFatal(0, "pthread_mutex_unlock failed\n");
return;
}
resp_freelist_inited = true;
if (pthread_mutex_unlock(&resp_mutex))
AssertFatal(0, "pthread_mutex_unlock failed\n");
int i;
for (i = 0; i < N_RESP - 1; i++)

View File

@@ -27,6 +27,7 @@
typedef void (*f1_setup_response_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_resp_t *resp);
typedef void (*f1_setup_failure_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *fail);
typedef void (*gnb_du_configuration_update_ack_func_t)(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack);
typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req);
typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req);

View File

@@ -36,6 +36,12 @@ static void f1_setup_failure_direct(sctp_assoc_t assoc_id, const f1ap_setup_fail
f1_setup_failure(fail);
}
static void gnb_du_configuration_update_ack_direct(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack)
{
AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id);
gnb_du_configuration_update_acknowledge(ack);
}
static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req)
{
AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id);
@@ -76,6 +82,7 @@ void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc)
{
mac_rrc->f1_setup_response = f1_setup_response_direct;
mac_rrc->f1_setup_failure = f1_setup_failure_direct;
mac_rrc->gnb_du_configuration_update_acknowledge = gnb_du_configuration_update_ack_direct;
mac_rrc->ue_context_setup_request = ue_context_setup_request_direct;
mac_rrc->ue_context_modification_request = ue_context_modification_request_direct;
mac_rrc->ue_context_modification_confirm = ue_context_modification_confirm_direct;

View File

@@ -44,6 +44,15 @@ static void f1_setup_failure_f1ap(sctp_assoc_t assoc_id, const f1ap_setup_failur
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
}
static void gnb_du_configuration_update_ack_f1ap(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack)
{
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE);
msg->ittiMsgHeader.originInstance = assoc_id;
f1ap_gnb_du_configuration_update_acknowledge_t *f1ap_msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg);
*f1ap_msg = *ack;
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
}
static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req)
{
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ);
@@ -194,6 +203,7 @@ void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc)
{
mac_rrc->f1_setup_response = f1_setup_response_f1ap;
mac_rrc->f1_setup_failure = f1_setup_failure_f1ap;
mac_rrc->gnb_du_configuration_update_acknowledge = gnb_du_configuration_update_ack_f1ap;
mac_rrc->ue_context_setup_request = ue_context_setup_request_f1ap;
mac_rrc->ue_context_modification_request = ue_context_modification_request_f1ap;
mac_rrc->ue_context_modification_confirm = ue_context_modification_confirm_f1ap;

View File

@@ -829,6 +829,10 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay){
//TODO change to accomodate for SRS
if (scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count > 0) {
LOG_W(RRC, "%s(): already have pusch_TimeDomainAllocationList members, not adding more\n", __func__);
return;
}
frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
const int k2 = min_fb_delay;

View File

@@ -346,6 +346,7 @@ typedef struct {
typedef struct nr_mac_rrc_dl_if_s {
f1_setup_response_func_t f1_setup_response;
f1_setup_failure_func_t f1_setup_failure;
gnb_du_configuration_update_ack_func_t gnb_du_configuration_update_acknowledge;
ue_context_setup_request_func_t ue_context_setup_request;
ue_context_modification_request_func_t ue_context_modification_request;
ue_context_modification_confirm_func_t ue_context_modification_confirm;

View File

@@ -122,6 +122,20 @@ mui_t rrc_gNB_mui = 0;
} \
}
typedef struct deliver_ue_ctxt_release_data_t {
gNB_RRC_INST *rrc;
f1ap_ue_context_release_cmd_t *release_cmd;
sctp_assoc_t assoc_id;
} deliver_ue_ctxt_release_data_t;
static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
{
DevAssert(deliver_pdu_data != NULL);
deliver_ue_ctxt_release_data_t *data = deliver_pdu_data;
data->release_cmd->rrc_container = (uint8_t*) buf;
data->release_cmd->rrc_container_length = size;
data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd);
}
///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------///
@@ -1834,7 +1848,18 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p)
gNB_RRC_INST *rrc = RC.nrrrc[instance];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, req->gNB_CU_ue_id);
if (!ue_context_p) {
LOG_E(RRC, "could not find UE context for CU UE ID %u, aborting transaction\n", req->gNB_CU_ue_id);
LOG_W(RRC, "could not find UE context for CU UE ID %u: auto-generate release command\n", req->gNB_CU_ue_id);
uint8_t buffer[RRC_BUF_SIZE] = {0};
int size = do_NR_RRCRelease(buffer, RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(0));
f1ap_ue_context_release_cmd_t ue_context_release_cmd = {
.gNB_CU_ue_id = req->gNB_CU_ue_id,
.gNB_DU_ue_id = req->gNB_DU_ue_id,
.cause = F1AP_CAUSE_RADIO_NETWORK,
.cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release
.srb_id = DCCH,
};
deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd};
nr_pdcp_data_req_srb(req->gNB_CU_ue_id, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data);
return;
}
@@ -2280,6 +2305,7 @@ void *rrc_gnb_task(void *args_p) {
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n");
timer_remove(stats_timer_id);
itti_exit_task();
break;
@@ -2368,6 +2394,11 @@ void *rrc_gnb_task(void *args_p) {
rrc_CU_process_f1_lost_connection(RC.nrrrc[0], &F1AP_LOST_CONNECTION(msg_p), msg_p->ittiMsgHeader.originInstance);
break;
case F1AP_GNB_DU_CONFIGURATION_UPDATE:
AssertFatal(!NODE_IS_DU(RC.nrrrc[instance]->node_type), "should not receive F1AP_SETUP_REQUEST in DU!\n");
rrc_gNB_process_f1_du_configuration_update(&F1AP_GNB_DU_CONFIGURATION_UPDATE(msg_p), msg_p->ittiMsgHeader.originInstance);
break;
/* Messages from X2AP */
case X2AP_ENDC_SGNB_ADDITION_REQ:
LOG_I(NR_RRC, "Received ENDC sgNB addition request from X2AP \n");
@@ -2534,20 +2565,6 @@ rrc_gNB_generate_UECapabilityEnquiry(
nr_rrc_transfer_protected_rrc_message(rrc, ue, DCCH, buffer, size);
}
typedef struct deliver_ue_ctxt_release_data_t {
gNB_RRC_INST *rrc;
f1ap_ue_context_release_cmd_t *release_cmd;
sctp_assoc_t assoc_id;
} deliver_ue_ctxt_release_data_t;
static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
{
DevAssert(deliver_pdu_data != NULL);
deliver_ue_ctxt_release_data_t *data = deliver_pdu_data;
data->release_cmd->rrc_container = (uint8_t*) buf;
data->release_cmd->rrc_container_length = size;
data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd);
}
//-----------------------------------------------------------------------------
/*
* Generate the RRC Connection Release to UE.

View File

@@ -48,6 +48,39 @@ static bool rrc_gNB_plmn_matches(const gNB_RRC_INST *rrc, const f1ap_served_cell
&& conf->mnc[0] == info->plmn.mnc;
}
static bool extract_sys_info(const f1ap_gnb_du_system_info_t *sys_info, NR_BCCH_BCH_Message_t **mib, NR_SIB1_t **sib1)
{
DevAssert(sys_info != NULL);
DevAssert(mib != NULL);
DevAssert(sib1 != NULL);
asn_dec_rval_t dec_rval =
uper_decode_complete(NULL, &asn_DEF_NR_BCCH_BCH_Message, (void **)mib, sys_info->mib, sys_info->mib_length);
if (dec_rval.code != RC_OK || (*mib)->message.present != NR_BCCH_BCH_MessageType_PR_mib
|| (*mib)->message.choice.messageClassExtension == NULL) {
LOG_E(RRC, "Failed to decode NR_BCCH_BCH_MESSAGE (%zu bits) of DU\n", dec_rval.consumed);
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, *mib);
return false;
}
if (sys_info->sib1) {
dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_SIB1, (void **)sib1, sys_info->sib1, sys_info->sib1_length);
if (dec_rval.code != RC_OK) {
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, *mib);
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, *sib1);
LOG_E(RRC, "Failed to decode NR_SIB1 (%zu bits), rejecting DU\n", dec_rval.consumed);
return false;
}
}
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_BCCH_BCH_Message, *mib);
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_SIB1, *sib1);
return true;
}
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");
@@ -110,35 +143,17 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
}
}
// if there is no system info or no SIB1 and we run in SA mode, we cannot handle it
const f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info;
NR_BCCH_BCH_Message_t *mib = NULL;
NR_SIB1_t *sib1 = NULL;
if (sys_info != NULL && sys_info->mib != NULL && !(sys_info->sib1 == NULL && get_softmodem_params()->sa)) {
asn_dec_rval_t dec_rval =
uper_decode_complete(NULL, &asn_DEF_NR_BCCH_BCH_Message, (void **)&mib, sys_info->mib, sys_info->mib_length);
if (dec_rval.code != RC_OK || mib->message.present != NR_BCCH_BCH_MessageType_PR_mib
|| mib->message.choice.messageClassExtension == NULL) {
LOG_E(RRC, "Failed to decode NR_BCCH_BCH_MESSAGE (%zu bits) of DU, rejecting DU\n", dec_rval.consumed);
if (!extract_sys_info(sys_info, &mib, &sib1)) {
LOG_W(RRC, "rejecting DU ID %ld\n", req->gNB_DU_id);
f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error};
rrc->mac_rrc.f1_setup_failure(assoc_id, &fail);
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, mib);
return;
}
if (sys_info->sib1) {
dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_SIB1, (void **)&sib1, sys_info->sib1, sys_info->sib1_length);
if (dec_rval.code != RC_OK) {
LOG_E(RRC, "Failed to decode NR_SIB1 (%zu bits) of DU, rejecting DU\n", dec_rval.consumed);
f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error};
rrc->mac_rrc.f1_setup_failure(assoc_id, &fail);
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, sib1);
return;
}
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_SIB1, sib1);
}
}
LOG_I(RRC, "Accepting DU %ld (%s), sending F1 Setup Response\n", req->gNB_DU_id, req->gNB_DU_name);
LOG_I(RRC, "DU uses RRC version %u.%u.%u\n", req->rrc_ver[0], req->rrc_ver[1], req->rrc_ver[2]);
@@ -154,12 +169,11 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
du->setup_req = calloc(1,sizeof(*du->setup_req));
AssertFatal(du->setup_req != NULL, "out of memory\n");
*du->setup_req = *req;
if (mib != NULL && sib1 != NULL) {
du->mib = mib->message.choice.mib;
mib->message.choice.mib = NULL;
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_MessageType, mib);
du->sib1 = sib1;
}
DevAssert(mib != NULL);
du->mib = mib->message.choice.mib;
mib->message.choice.mib = NULL;
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_MessageType, mib);
du->sib1 = sib1;
RB_INSERT(rrc_du_tree, &rrc->dus, du);
rrc->num_dus++;
@@ -178,28 +192,6 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
if (rrc->node_name != NULL)
resp.gNB_CU_name = strdup(rrc->node_name);
rrc->mac_rrc.f1_setup_response(assoc_id, &resp);
/*
MessageDef *msg_p2 = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE);
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).gNB_CU_name = rrc->node_name;
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].plmn.mcc = rrc->configuration.mcc[0];
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].plmn.mnc = rrc->configuration.mnc[0];
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].plmn.mnc_digit_length = rrc->configuration.mnc_digit_length[0];
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].nr_cellid = rrc->nr_cellid;
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].nrpci = req->cell[0].info.nr_pci;
int num_SI = 0;
if (rrc->carrier.SIB23) {
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].SI_container[2] = rrc->carrier.SIB23;
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].SI_container_length[2] = rrc->carrier.sizeof_SIB23;
num_SI++;
}
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).cells_to_activate[0].num_SI = num_SI;
F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p2).num_cells_to_activate = 1;
// send
itti_send_msg_to_task(TASK_CU_F1, 0, msg_p2);
*/
}
static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
@@ -221,6 +213,103 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
return count;
}
static void update_cell_info(nr_rrc_du_container_t *du, const f1ap_served_cell_info_t *new_ci)
{
DevAssert(du != NULL);
DevAssert(new_ci != NULL);
AssertFatal(du->setup_req->num_cells_available == 1, "expected 1 cell for DU, but has %d\n", du->setup_req->num_cells_available);
f1ap_served_cell_info_t *ci = &du->setup_req->cell[0].info;
ci->nr_cellid = new_ci->nr_cellid;
ci->nr_pci = new_ci->nr_pci;
if (new_ci->tac != NULL)
*ci->tac = *new_ci->tac;
ci->num_ssi = new_ci->num_ssi;
ci->sst = new_ci->sst;
ci->sd = new_ci->sd;
ci->mode = new_ci->mode;
if (ci->mode == F1AP_MODE_TDD)
ci->tdd = new_ci->tdd;
else
ci->fdd = new_ci->fdd;
}
void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update_t *conf_up, sctp_assoc_t assoc_id)
{
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
gNB_RRC_INST *rrc = RC.nrrrc[0];
DevAssert(rrc);
// check:
// - it is one cell
// - PLMN and Cell ID matches
// - no previous DU with the same ID
// else reject
nr_rrc_du_container_t *du = get_du_by_assoc_id(rrc, assoc_id);
AssertError(du != NULL, return, "no DU found for assoc_id %d\n", assoc_id);
const f1ap_served_cell_info_t *info = &du->setup_req->cell[0].info;
if(conf_up->num_cells_to_add > 0){
// Here we check if the number of cell limit is respectet, otherwise send failure
LOG_W(RRC, "du_configuration_update->cells_to_add_list is not supported yet");
}
if(conf_up->num_cells_to_modify > 0){
// here the old nrcgi is used to find the cell information, if it exist then we modify consequently otherwise we fail
AssertFatal(conf_up->num_cells_to_modify == 1, "cannot handle more than one cell!\n");
if (info->nr_cellid != conf_up->cell_to_modify[0].old_nr_cellid) {
LOG_W(RRC, "no cell with ID %ld found, ignoring gNB-DU configuration update\n", conf_up->cell_to_modify[0].old_nr_cellid);
return;
}
// verify the new plmn of the cell
if (!rrc_gNB_plmn_matches(rrc, &conf_up->cell_to_modify[0].info)) {
LOG_W(RRC, "PLMN does not match, ignoring gNB-DU configuration update\n");
return;
}
update_cell_info(du, &conf_up->cell_to_modify[0].info);
const f1ap_gnb_du_system_info_t *sys_info = conf_up->cell_to_modify[0].sys_info;
if (sys_info != NULL && sys_info->mib != NULL && !(sys_info->sib1 == NULL && get_softmodem_params()->sa)) {
// MIB is mandatory, so will be overwritten. SIB1 is optional, so will
// only be overwritten if present in sys_info
ASN_STRUCT_FREE(asn_DEF_NR_MIB, du->mib);
if (sys_info->sib1 != NULL) {
ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1);
du->sib1 = NULL;
}
NR_BCCH_BCH_Message_t *mib = NULL;
if (!extract_sys_info(sys_info, &mib, &du->sib1)) {
LOG_W(RRC, "cannot update sys_info for DU %ld\n", du->setup_req->gNB_DU_id);
} else {
DevAssert(mib != NULL);
du->mib = mib->message.choice.mib;
mib->message.choice.mib = NULL;
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_MessageType, mib);
LOG_I(RRC, "update system information of DU %ld\n", du->setup_req->gNB_DU_id);
}
}
}
if(conf_up->num_cells_to_delete > 0){
// delete the cell and send cell to desactive IE in the response.
LOG_W(RRC, "du_configuration_update->cells_to_delete_list is not supported yet");
}
/* Send DU Configuration Acknowledgement */
f1ap_gnb_du_configuration_update_acknowledge_t ack = {.transaction_id = conf_up->transaction_id};
rrc->mac_rrc.gnb_du_configuration_update_acknowledge(assoc_id, &ack);
}
void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id)
{
AssertFatal(assoc_id != 0, "illegal assoc_id == 0: should be -1 (monolithic) or >0 (split)\n");
@@ -276,5 +365,18 @@ void dump_du_info(const gNB_RRC_INST *rrc, FILE *f)
}
const f1ap_served_cell_info_t *info = &sr->cell[0].info;
fprintf(f, ": nrCellID %ld, PCI %d\n", info->nr_cellid, info->nr_pci);
if (info->mode == F1AP_MODE_TDD) {
const f1ap_nr_frequency_info_t *fi = &info->tdd.freqinfo;
const f1ap_transmission_bandwidth_t *tb = &info->tdd.tbw;
fprintf(f, " TDD: band %d ARFCN %d SCS %d (kHz) PRB %d\n", fi->band, fi->arfcn, 15 * (1 << tb->scs), tb->nrb);
} else {
const f1ap_nr_frequency_info_t *dfi = &info->fdd.dl_freqinfo;
const f1ap_transmission_bandwidth_t *dtb = &info->fdd.dl_tbw;
fprintf(f, " FDD: DL band %d ARFCN %d SCS %d (kHz) PRB %d\n", dfi->band, dfi->arfcn, 15 * ( 1 << dtb->scs), dtb->nrb);
const f1ap_nr_frequency_info_t *ufi = &info->fdd.ul_freqinfo;
const f1ap_transmission_bandwidth_t *utb = &info->fdd.ul_tbw;
fprintf(f, " UL band %d ARFCN %d SCS %d (kHz) PRB %d\n", ufi->band, ufi->arfcn, 15 * (1 << utb->scs), utb->nrb);
}
}
}

View File

@@ -31,9 +31,11 @@ struct f1ap_setup_req_s;
struct f1ap_lost_connection_t;
struct gNB_RRC_INST_s;
struct nr_rrc_du_container_t;
struct f1ap_gnb_du_configuration_update_s;
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_gNB_process_f1_du_configuration_update(struct f1ap_gnb_du_configuration_update_s *conf_up, sctp_assoc_t assoc_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);

View File

@@ -670,6 +670,15 @@ static int startServer(openair0_device *device) {
return 0;
}
static void rfsimulator_end(openair0_device *device);
static void stopServer(openair0_device *device)
{
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
DevAssert(t != NULL);
rfsimulator_end(device);
close(t->listen_sock);
}
static int startClient(openair0_device *device) {
rfsimulator_state_t *t = device->priv;
t->role = SIMU_ROLE_CLIENT;
@@ -1047,10 +1056,11 @@ static void rfsimulator_end(openair0_device *device) {
rfsimulator_state_t* s = device->priv;
for (int i = 0; i < MAX_FD_RFSIMU; i++) {
buffer_t *b = &s->buf[i];
if (b->conn_sock >= 0 )
close(b->conn_sock);
if (b->conn_sock >= 0 ) {
removeCirBuf(s, b->conn_sock);
}
}
close(s->epollfd);
//close(s->epollfd); // don't close as we cannot restart with startServer()/startClient()
}
static int rfsimulator_stop(openair0_device *device) {
return 0;
@@ -1084,7 +1094,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
device->trx_start_func = rfsimulator->role == SIMU_ROLE_SERVER ? startServer : startClient;
device->trx_get_stats_func = rfsimulator_get_stats;
device->trx_reset_stats_func = rfsimulator_reset_stats;
device->trx_end_func = rfsimulator_end;
device->trx_end_func = rfsimulator->role == SIMU_ROLE_SERVER ? stopServer : rfsimulator_end;
device->trx_stop_func = rfsimulator_stop;
device->trx_set_freq_func = rfsimulator_set_freq;
device->trx_set_gains_func = rfsimulator_set_gains;