From 574363c5157f49e52528f7deee182fbeb474cc04 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 27 Aug 2024 10:05:46 +0200 Subject: [PATCH 1/3] Correct order of PCI addresses in O-RAN 7.2 tutorial The correct order for xran seems to be first Uplane, then C plane. In the past, we used to switch (for reasons I don't know), but let's reverse it to the proper order. --- doc/ORAN_FHI7.2_Tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index a000a6c3ad..59372ae4e8 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -626,7 +626,7 @@ In the following, we will use these short hands: - `du-u-plane-mac-addr`: DU U plane MAC address - `pci-address-u-plane-vf`: PCI bus address of the VF for U plane -In the configuration file, in option `fhi_72.dpdk_devices`, the first PCI address is for C-plane and the second for U-plane. +In the configuration file, in option `fhi_72.dpdk_devices`, the first PCI address is for U-plane and the second for C-plane. For both the MAC addresses, you might use the MAC addresses which are pre-configured in the RUs (typically `00:11:22:33:44:66`, but that is not From 7e18293c7064ad57be1eefb639e2ad36d4d842de Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 16 Aug 2024 11:24:42 +0200 Subject: [PATCH 2/3] Changes for multi-RU support in fhi72 Co-authored-by: Robert Schmidt --- radio/fhi_72/oaioran.c | 11 ++++++++++- radio/fhi_72/oran-init.c | 8 ++++++-- radio/fhi_72/oran-init.h | 4 ++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 247293c18f..300a6869cf 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -92,10 +92,19 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) rx_sym = callback_tag->symbol; uint32_t ru_id = callback_tag->oXuId; + + LOG_D(NR_PHY, + "rx_callback frame %d, subframe %d, slot %d, second %lld, rx_sym %d ru_id %d\n", + frame, + subframe, + slot, + (unsigned long long)second, + rx_sym, + ru_id); if (rx_sym == 7) { if (first_call_set) { if (!first_rx_set) { - LOG_I(NR_PHY, "first_rx is set (num_ports %d)\n", num_ports); + LOG_I(NR_PHY, "first_rx is set (num_ports %d), first_read_set %d\n", num_ports, first_read_set); } first_rx_set = 1; if (first_read_set == 1) { diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index 8673b5d2b4..7a629ce5aa 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -392,8 +392,8 @@ static void oran_allocate_buffers(void *handle, } } - xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->RxCbTag[0][0]); - xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->PrachCbTag[0][0]); + xran_5g_fronthault_config(pi->instanceHandle, src, srccp, dst, dstcp, oai_xran_fh_rx_callback, &portInstances->pusch_tag); + xran_5g_prach_req(pi->instanceHandle, prach, prachdecomp, oai_xran_fh_rx_prach_callback, &portInstances->prach_tag); } int *oai_oran_initialize(const openair0_config_t *openair0_cfg) @@ -432,7 +432,11 @@ int *oai_oran_initialize(const openair0_config_t *openair0_cfg) } int sector = 0; + printf("Initialize ORAN port instance %d (%d) sector %d\n", o_xu_id, init.xran_ports, sector); oran_port_instance_t *pi = &gPortInst[o_xu_id][sector]; + struct xran_cb_tag tag = {.cellId = sector, .oXuId = o_xu_id}; + pi->prach_tag = tag; + pi->pusch_tag = tag; oran_allocate_buffers(gxran_handle, o_xu_id, 1, pi, &xran_fh_config[o_xu_id]); if ((xret = xran_reg_physide_cb(gxran_handle, oai_physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI)) != XRAN_STATUS_SUCCESS) { diff --git a/radio/fhi_72/oran-init.h b/radio/fhi_72/oran-init.h index 2c3e5a8ca0..dad57a60c3 100644 --- a/radio/fhi_72/oran-init.h +++ b/radio/fhi_72/oran-init.h @@ -50,8 +50,8 @@ typedef struct oran_port_instance_t { void *instanceHandle; //uint32_t dpdkPoolIndex[MAX_SW_XRAN_INTERFACE_NUM]; - struct xran_cb_tag RxCbTag[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR]; - struct xran_cb_tag PrachCbTag[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR]; + struct xran_cb_tag prach_tag; + struct xran_cb_tag pusch_tag; } oran_port_instance_t; extern struct xran_fh_config gxran_fh_config[XRAN_PORTS_NUM]; From 85f194b5c7c848d4013626c56811f49c073eac94 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 26 Aug 2024 17:29:10 +0200 Subject: [PATCH 3/3] Add documentation and sample config for FHI 7.2 multi-RU operation Co-authored-by: Raymond Knopp --- doc/ORAN_FHI7.2_Tutorial.md | 137 +++++++++ ...nd78.106prb.fhi72.8x8-benetel-650-550.conf | 289 ++++++++++++++++++ 2 files changed, 426 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.fhi72.8x8-benetel-650-550.conf diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index 59372ae4e8..0a4036423b 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -891,6 +891,143 @@ do not do any jumps (during the last hour). While an occasional jump is not necessarily problematic for the gNB, many such messages mean that the system is not working, and UEs might not be able to attach or reach good performance. +# Operation with multiple RUs + +It is possible to connect up to 4 RUs to one DU at the same time and operate +them as a (single) distributed antenna (array). This works since all RUs and +the DU are synchronized onto a common clock using PTP. The assumed +configuration is that with N RUs each having an M×M configuration, we +effectively reach an (N×M)×(N×M) configuration. + +Some caveats: +- Since it's a distributed antenna, this implies that this setup will deploy a + single cell only -- multiple cells on different RUs are not supported. +- All RUs should use the same MTU, so either "normal" (1500 byte) MTU or jumbo + frames, but not a mix of both. +- We tested only two RUs as of now, i.e., an 8×8 configuration. +- Testing is currently limited to 4 logical antenna ports in DL; in UL, up to 8 can be used. + +For two RUs each using a 4x4 configuration, make sure to configure the 8x8 +configuration, i.e., set `nb_tx` and `nb_rx` under `RUs` to 8 each (NOT two +RUs!). Also, set the antenna port information as listed above, i.e., + +``` +pdsch_AntennaPorts_XP = 2; +pdsch_AntennaPorts_N1 = 2; +pusch_AntennaPorts = 8; +maxMIMO_layers = 2; +``` +Once testing for 8 antenna ports in DL is complete, we will change pdsch_AntennaPorts_N1 to 4. + +Next, configure the `fhi_72` section as indicated below: + +``` +fhi_72 = { + dpdk_devices = ("ru1_up_vf_pci", "ru1_cp_vf_pci", "ru2_up_vf_pci", "ru2_cp_vf_pci"); + // core config as always + du_addr = ("du_ru1_up_mac_addr", "du_ru1_cp_mac_addr", "du_ru2_up_mac_addr", "du_ru2_cp_mac_addr"); + ru_addr = ("ru1_up_mac_addr", "ru1_cp_mac_addr", "ru2_up_mac_addr", "ru2_cp_mac_addr"); + // mtu, file_prefix ... + fh_config = ( + { + // timing, ru_config, prach_config of RU1 + }, + { + // timing, ru_config, prach_config of RU2 + } + ); +}; +``` + +i.e., for `dpdk_devices`, `du_addr`, and `ru_addr` is configured for +both RUs in a (flat) array, and the individual radio configuration is given for +each RU individually inside the `fh_config`. + +
+Sample FHI 7.2 configuration for two RUs (Benetel 550 and 650) + +``` +fhi_72 = { + dpdk_devices = ("0000:01:01.0", "0000:01:01.1", "0000:01:01.2", "0000:01:01.3"); + system_core = 0; + io_core = 1; + worker_cores = (2); + du_addr = ("00:11:22:33:44:66","00:11:22:33:44:67","00:11:22:33:44:66","00:11:22:33:44:67"); + ru_addr = ("70:b3:d5:e1:5b:ff","70:b3:d5:e1:5b:ff","70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81"); + mtu = 9216; + file_prefix = "fhi_72"; + fh_config = ( +# RAN650 + { + Tadv_cp_dl = 125; + T2a_cp_dl = (259, 500); + T2a_cp_ul = (25, 500); + T2a_up = (134, 375); + Ta3 = (152, 160); + T1a_cp_dl = (419, 470); + T1a_cp_ul = (285, 336); + T1a_up = (294, 345); + Ta4 = (0, 200); + ru_config = { + iq_width = 9; + iq_width_prach = 9; + }; + prach_config = { + eAxC_offset = 4; + }; + }, +# RAN550 + { + Tadv_cp_dl = 125; + T2a_cp_dl = (259, 500); + T2a_cp_ul = (25, 500); + T2a_up = (134, 375); + Ta3 = (152, 160); + T1a_cp_dl = (419, 470); + T1a_cp_ul = (285, 336); + T1a_up = (294, 345); + Ta4 = (0, 200); + ru_config = { + iq_width = 9; + iq_width_prach = 9; + }; + prach_config = { + eAxC_offset = 4; + }; + }); +``` +
+ +Compare also with the example (DU) configuration in +[`gnb-du.sa.band78.106prb.fhi72.8x8-benetel-650-550.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.fhi72.8x8-benetel-650-550.conf). + +Afterwards, start the gNB with the modified configuration file. If everything +went well, you should see the RU counters for both RUs go up: + +``` +[NR_PHY] [o-du 0][rx 614400 pps 61440 kbps 844953][tx 1275076 pps 127488 kbps 1998585][Total Msgs_Rcvd 614400] +[NR_PHY] [o_du0][pusch0 107520 prach0 46080] +[NR_PHY] [o_du0][pusch1 107520 prach1 46080] +[NR_PHY] [o_du0][pusch2 107520 prach2 46080] +[NR_PHY] [o_du0][pusch3 107520 prach3 46080] +[NR_PHY] [o-du 1][rx 614400 pps 61440 kbps 844953][tx 1275076 pps 127488 kbps 1998585][Total Msgs_Rcvd 614400] +[NR_PHY] [o_du1][pusch0 107520 prach0 46080] +[NR_PHY] [o_du1][pusch1 107520 prach1 46080] +[NR_PHY] [o_du1][pusch2 107520 prach2 46080] +[NR_PHY] [o_du1][pusch3 107520 prach3 46080] +``` + +You can also verify that there is signal on all RX antennas like so: +```bash +$ cat nrL1_stats.log +[...] +max_IO = 66 (81), min_I0 = 0 (53), avg_I0 = 51 dB(46.48.45.46.51.56.55.45.) +PRACH I0 = 38.0 dB +``` + +Note the eight entries after `avg_IO`. + +You should be able to connect a UE now. # Contact in case of questions diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.fhi72.8x8-benetel-650-550.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.fhi72.8x8-benetel-650-550.conf new file mode 100644 index 0000000000..edc7dd276f --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band78.106prb.fhi72.8x8-benetel-650-550.conf @@ -0,0 +1,289 @@ +Active_gNBs = ( "gNB-OAI-DU"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; + gNB_name = "gNB-OAI-DU"; + + // 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 = 1; + + ////////// Physical parameters: + + pdsch_AntennaPorts_XP = 2; + pdsch_AntennaPorts_N1 = 2; + pusch_AntennaPorts = 8; + do_CSIRS = 1; + do_SRS = 0 ; + sib1_tda = 15; +# force_UL256qam_off = 1; + maxMIMO_layers = 2; + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 11; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + # n_TimingAdvanceOffset = 0; +# downlinkConfigCommon + #frequencyInfoDL + # this is 3430.56 MHz (center frequency) + absoluteFrequencySSB = 628704; + dl_frequencyBand = 78; + # this is 3411.48 MHz + dl_absoluteFrequencyPointA = 627432; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + initialDLBWPlocationAndBandwidth = 28875; #38.101-1 Table 5.3.2-1 + # +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + 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 = 23; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 154; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 0; + preambleReceivedTargetPower = -100; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 8; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 3; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + +# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB + msg3_DeltaPreamble = 2; + p0_NominalWithGrant = -96; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 0; + p0_nominal = -96; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 0x10001L; + +# 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 +# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 8=ms3 9=ms4 + referenceSubcarrierSpacing = 1; + dl_UL_TransmissionPeriodicity = 8; + nrofDownlinkSlots = 3; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 10; + } + + ); + + + # ------- 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 = "enp193s0f0"; + local_n_address = "172.21.16.51"; + remote_n_address = "172.21.6.90"; + local_n_portc = 500; + local_n_portd = 2153; + remote_n_portc = 501; + remote_n_portd = 2153; + pusch_TargetSNRx10 = 230; + pucch_TargetSNRx10 = 270; + dl_bler_target_upper = .35; + dl_bler_target_lower = .15; + ul_bler_target_upper = .35; + ul_bler_target_lower = .15; + pusch_FailureThres = 100; + ul_max_mcs = 28; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 100; + pucch0_dtx_threshold = 80; + pusch_dtx_threshold = 10; + max_ldpc_iterations = 10; + tx_amp_backoff_dB = 12; # needs to match O-RU configuration + L1_rx_thread_core = 8; + L1_tx_thread_core = 10; # relevant after merge of l1_tx_thread + phase_compensation = 0; # needs to match O-RU configuration +} +); + +RUs = ( +{ + local_rf = "no"; + nb_tx = 8; + nb_rx = 8; + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + sf_extension = 0; + eNB_instances = [0]; + ru_thread_core = 9; + sl_ahead = 10; + clock_src = "internal"; + tr_preference = "raw_if4p5"; # important: activate FHI7.2 + do_precoding = 0; # needs to match O-RU configuration +} +); + +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"; +}; + +fhi_72 = { + dpdk_devices = ("0000:01:01.0", "0000:01:01.1", "0000:01:01.2", "0000:01:01.3"); + system_core = 0; + io_core = 1; + worker_cores = (2); + du_addr = ("00:11:22:33:44:66","00:11:22:33:44:67","00:11:22:33:44:68","00:11:22:33:44:69"); + ru_addr = ("70:b3:d5:e1:5b:ff","70:b3:d5:e1:5b:ff","70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81"); + mtu = 9216; + file_prefix = "fhi_72"; + fh_config = ( +# RAN650 + { + Tadv_cp_dl = 125; + T2a_cp_dl = (259, 500); + T2a_cp_ul = (25, 500); + T2a_up = (134, 375); + Ta3 = (152, 160); + T1a_cp_dl = (419, 470); + T1a_cp_ul = (285, 336); + T1a_up = (294, 345); + Ta4 = (0, 200); + ru_config = { + iq_width = 9; + iq_width_prach = 9; + }; + prach_config = { + eAxC_offset = 4; + }; + }, +# RAN550 + { + Tadv_cp_dl = 125; + T2a_cp_dl = (259, 500); + T2a_cp_ul = (25, 500); + T2a_up = (134, 375); + Ta3 = (152, 160); + T1a_cp_dl = (419, 470); + T1a_cp_ul = (285, 336); + T1a_up = (294, 345); + Ta4 = (0, 200); + ru_config = { + iq_width = 9; + iq_width_prach = 9; + }; + prach_config = { + eAxC_offset = 4; + }; + }); +};