From e17350a10d3512545b2be29bb5889fc71956365c Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 9 Feb 2026 16:13:01 +0100 Subject: [PATCH 01/33] Adjust ssPBCH_BlockPower in FHI7.2 configs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compute ssPBCH_BlockPower from RU max TX power and bandwidth ssPBCH_BlockPower = P_TX(dBm) − 10 x log10(N_RB x 12) Assume P_TX = 24 dBm for indoor RUs and 35 dBm for outdoor RUs. --- .../conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf | 2 +- .../CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf | 2 +- .../gnb-du.sa.band77.273prb.fhi72.4x4-das-benetel650_650.conf | 2 +- ...gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf | 2 +- .../CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf | 2 +- .../CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf | 2 +- .../CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn-16b.conf | 2 +- .../CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf | 2 +- .../CONF/gnb.sa.band78.273prb.fhi72.2x2-benetel550-16b.conf | 2 +- .../CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf | 2 +- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf | 2 +- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf | 2 +- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf | 2 +- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf | 2 +- .../CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf b/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf index 885f561bec..cfeea1ff90 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf @@ -145,7 +145,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = -15; + ssPBCH_BlockPower = -11; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf index e590443239..c9a9b4833c 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf @@ -146,7 +146,7 @@ gNBs = nrofUplinkSlots = 1; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 5; + ssPBCH_BlockPower = 0; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-das-benetel650_650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-das-benetel650_650.conf index 4a5553006a..d557f03341 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-das-benetel650_650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-das-benetel650_650.conf @@ -146,7 +146,7 @@ gNBs = nrofUplinkSlots = 1; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = 0; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf index eee6f875c9..a3694799dd 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf @@ -146,7 +146,7 @@ gNBs = nrofUplinkSlots = 1; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = 0; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf index 253d312eb0..0e2a83518c 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf @@ -146,7 +146,7 @@ gNBs = nrofUplinkSlots = 1; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 10; + ssPBCH_BlockPower = 0; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf index 5ff25d5f43..28936ab689 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf @@ -144,7 +144,7 @@ gNBs = nrofUplinkSlots = 1; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 0; + ssPBCH_BlockPower = -7; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn-16b.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn-16b.conf index 92ba13f7ce..eb6a8d564c 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn-16b.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn-16b.conf @@ -142,7 +142,7 @@ gNBs = nrofUplinkSlots = 1; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 0; + ssPBCH_BlockPower = -11; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf index 2e16cf50a5..1a34d28f50 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf @@ -144,7 +144,7 @@ gNBs = nrofUplinkSlots = 1; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 0; + ssPBCH_BlockPower = -11; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.2x2-benetel550-16b.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.2x2-benetel550-16b.conf index eb304d01fd..5d15d78477 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.2x2-benetel550-16b.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.2x2-benetel550-16b.conf @@ -145,7 +145,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 0; + ssPBCH_BlockPower = -11; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf index 43d6ffd760..8adb2d7113 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf @@ -143,7 +143,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 0; + ssPBCH_BlockPower = -11; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf index 241ca9f23a..97e737b0dc 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf @@ -145,7 +145,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 0; + ssPBCH_BlockPower = -11; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf index 39636baa54..2d2d2de5e8 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf @@ -145,7 +145,7 @@ gNBs = nrofUplinkSlots = 2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 0; + ssPBCH_BlockPower = -11; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf index 7f6845d8cd..606ffa9d01 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-foxconn.conf @@ -144,7 +144,7 @@ gNBs = nrofUplinkSlots = 1; #2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 0; + ssPBCH_BlockPower = -11; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf index 0c1ef0b2e8..a37a40990b 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf @@ -144,7 +144,7 @@ gNBs = nrofUplinkSlots = 1; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = 0; + ssPBCH_BlockPower = -11; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf index 322d61b2b3..5d0d15d47b 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf @@ -130,7 +130,7 @@ gNBs = nrofDownlinkSymbols = 6; nrofUplinkSlots = 1; #2; nrofUplinkSymbols = 4; - ssPBCH_BlockPower = -10; + ssPBCH_BlockPower = -11; } ); # ------- SCTP definitions From 36f24d94c3dc4b6123402c5bef518740d834b302 Mon Sep 17 00:00:00 2001 From: andrewse Date: Fri, 6 Mar 2026 12:06:01 +0000 Subject: [PATCH 02/33] demoted "PUCCH list is full" message to a warning --- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 61bdce06b2..62af37cdc8 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -58,7 +58,6 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu) { - bool found = false; for (int i = 0; i < gNB->max_nb_pucch; i++) { NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; if (pucch->active == false) { @@ -86,11 +85,10 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t pucch->pucch_pdu.bit_len_harq, pucch->pucch_pdu.sr_flag, pucch->pucch_pdu.bit_len_csi_part1); - found = true; - break; + return; } } - AssertFatal(found, "PUCCH list is full\n"); + LOG_W(PHY, "PUCCH list is full\n"); } From 81c1479429830e90cfaebaa3c6d95ee67daa9d68 Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Thu, 5 Mar 2026 17:00:04 +0100 Subject: [PATCH 03/33] UE PHY-TEST : phy-test mode works now in NTN params_changed flag is set to true when reconfig.raw file gets processed, as NTN config is present in reconfiguration. but due to this initialisation happening at a later point params_changed is reset which results in incorrect writes on RFsimulator --- executables/nr-ue.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 75814596d3..fdaa4f4671 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -177,8 +177,6 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id) ue->dci_thres = 0; ue->target_Nid_cell = -1; - ue->nrUE_config.ntn_config.params_changed = false; - // initialize all signal buffers init_nr_ue_signal(ue, nb_connected_gNB); From eaaf880d37a10623fbe7ec9a7f2554e1a78b7a1a Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Fri, 6 Mar 2026 10:15:26 +0100 Subject: [PATCH 04/33] gNB: skip CU and DU SIBs if not SA mode --- openair2/GNB_APP/gnb_config.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index d3618bdaaf..0323339c79 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1255,6 +1255,11 @@ static seq_arr_t *fill_du_sibs(paramdef_t *GNBparamarray) if (GNBparamarray[GNB_DU_SIBS_IDX].numelt == 0) return NULL; + if (!IS_SA_MODE(get_softmodem_params())) { + LOG_E(GNB_APP, "DU SIBs only supported in SA mode, we'll skip them!\n"); + return NULL; + } + seq_arr_t *du_SIBs = malloc(sizeof(seq_arr_t)); seq_arr_init(du_SIBs, sizeof(nr_SIBs_t)); for (int i = 0; i < GNBparamarray[GNB_DU_SIBS_IDX].numelt; i++) { @@ -1795,6 +1800,11 @@ static seq_arr_t *fill_cu_sibs(paramdef_t *GNBparamarray) if (GNBparamarray[GNB_CU_SIBS_IDX].numelt == 0) return NULL; + if (!IS_SA_MODE(get_softmodem_params())) { + LOG_E(GNB_APP, "CU SIBs only supported in SA mode, we'll skip them!\n"); + return NULL; + } + seq_arr_t *SIBs = malloc(sizeof(seq_arr_t)); seq_arr_init(SIBs, sizeof(nr_SIBs_t)); for (int i = 0; i < GNBparamarray[GNB_CU_SIBS_IDX].numelt; i++) { From f0394364fd10b5831a86f2495cc6331e596a4a86 Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Thu, 5 Mar 2026 17:00:57 +0100 Subject: [PATCH 05/33] gNB PHY-TEST: Introduced --Dmod/Umod option for scheduling slot >= 64 in FR2-FDD case --Dmod option/--Umod option, for example --Dmod 1 will schedule every slot in slots per frame --Dmod 3 will schedule every 3rd slot. You can use --Dmod option togethor with -D option same for uplink scheduling too. for FR2 with 120Khz scs, there are 80 slots. Removed the assert such that FR2 config can be tested in phy-test, currently bitmap works only until 64 slots. --- executables/nr-softmodem-common.h | 2 ++ executables/nr-softmodem.h | 4 ++++ openair1/PHY/TOOLS/calibration_test.c | 2 ++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 20 +++++++++++++------ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h index bcbd138128..202b518081 100644 --- a/executables/nr-softmodem-common.h +++ b/executables/nr-softmodem-common.h @@ -55,5 +55,7 @@ #define CONFIG_HLP_ULBW_PHYTEST "Set the number of PRBs used for ULSCH in PHYTEST mode\n" #define CONFIG_HLP_DLBM_PHYTEST "Bitmap for DLSCH slots in period (slot 0 starts at LSB)\n" #define CONFIG_HLP_ULBM_PHYTEST "Bitmap for ULSCH slots in period (slot 0 starts at LSB)\n" +#define CONFIG_HLP_DLMOD_PHYTEST "For-DLSCH, if val is n, every nth slot in slots per frame will be scheduled. \n" +#define CONFIG_HLP_ULMOD_PHYTEST "For ULSCH, if val is n, every nth slot in slots per frame will be scheduled. \n" void wait_gNBs(void); #endif diff --git a/executables/nr-softmodem.h b/executables/nr-softmodem.h index 08bee0d2d8..f460a9d934 100644 --- a/executables/nr-softmodem.h +++ b/executables/nr-softmodem.h @@ -25,6 +25,8 @@ {"T" , CONFIG_HLP_ULBW_PHYTEST, 0, .uptr=&target_ul_bw, .defintval=0, TYPE_UINT, 0}, \ {"D" , CONFIG_HLP_DLBM_PHYTEST, 0, .u64ptr=&dlsch_slot_bitmap, .defint64val=0, TYPE_UINT64, 0}, \ {"U" , CONFIG_HLP_ULBM_PHYTEST, 0, .u64ptr=&ulsch_slot_bitmap, .defint64val=0, TYPE_UINT64, 0}, \ + {"Dmod" , CONFIG_HLP_DLMOD_PHYTEST, 0, .uptr=&dlsch_slot_modval, .defintval=0, TYPE_UINT, 0}, \ + {"Umod" , CONFIG_HLP_ULMOD_PHYTEST, 0, .uptr=&ulsch_slot_modval, .defintval=0, TYPE_UINT, 0}, \ {"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, .iptr=&usrp_tx_thread, .defstrval=0, TYPE_INT, 0}, \ {"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \ } @@ -39,6 +41,8 @@ extern uint32_t target_ul_bw; extern uint64_t dlsch_slot_bitmap; extern uint64_t ulsch_slot_bitmap; extern char *uecap_file; +extern uint32_t dlsch_slot_modval; +extern uint32_t ulsch_slot_modval; // In nr-gnb.c extern void init_gNB(); diff --git a/openair1/PHY/TOOLS/calibration_test.c b/openair1/PHY/TOOLS/calibration_test.c index 05420672ad..f4a31e9cfd 100644 --- a/openair1/PHY/TOOLS/calibration_test.c +++ b/openair1/PHY/TOOLS/calibration_test.c @@ -23,6 +23,8 @@ uint32_t target_dl_bw = 50; uint32_t target_dl_Nl; uint32_t target_ul_Nl; char *uecap_file; +uint32_t dlsch_slot_modval; +uint32_t ulsch_slot_modval; #include int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_state) {return 0;} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index f23dfe8b30..7afcbf35d2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -42,17 +42,24 @@ /* This function checks whether the given Dl/UL slot is set in the input bitmap (per period), which is a mask indicating in which - slot to transmit (among those available in the TDD configuration) */ -static bool is_xlsch_in_slot(uint64_t bitmap, slot_t slot) + slot to transmit (among those available in the TDD configuration) + This function also checks if Dmod/Umod option is set, then the slot will be + scheduled in case slot % val == 0. + Use Dmod/Umod in case of FDD FR2. */ +static bool is_xlsch_in_slot(uint64_t bitmap, uint32_t modval, slot_t slot) { - AssertFatal(slot < 64, "Unable to handle periods with length larger than 64 slots in phy-test mode\n"); - return (bitmap >> slot) & 0x01; + AssertFatal(modval || slot < 64, "Slot >= 64 cannot be scheduled using options 'D/U', use 'Dmod/Umod' option\n"); + + bool val1 = (bitmap >> slot) & 0x01; + bool val2 = (modval && (slot % modval == 0)); + return (val1 || val2); } uint32_t target_dl_mcs = 9; uint32_t target_dl_Nl = 1; uint32_t target_dl_bw = 50; uint64_t dlsch_slot_bitmap = (1<<1); +uint32_t dlsch_slot_modval = 0; /* schedules whole bandwidth for first user, all the time */ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) @@ -62,7 +69,7 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ int slot_period = slot % mac->frame_structure.numb_slots_period; - if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot_period)) + if (!is_xlsch_in_slot(dlsch_slot_bitmap, dlsch_slot_modval, slot_period)) return; NR_UE_info_t *UE = mac->UE_info.connected_ue_list[0]; NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; @@ -218,6 +225,7 @@ uint32_t target_ul_mcs = 9; uint32_t target_ul_bw = 50; uint32_t target_ul_Nl = 1; uint64_t ulsch_slot_bitmap = (1 << 8); +uint32_t ulsch_slot_modval = 0; void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_pusch) { int frame = pp_pusch->frame; @@ -267,7 +275,7 @@ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_p * limitations). Note that if K2 or the TDD configuration is changed, below * conditions might exclude each other and never be true */ int slot_period = sched_slot % nr_mac->frame_structure.numb_slots_period; - if (!is_xlsch_in_slot(ulsch_slot_bitmap, slot_period)) + if (!is_xlsch_in_slot(ulsch_slot_bitmap, ulsch_slot_modval, slot_period)) return; // TODO implement beam procedures for phy-test mode From 3dbc5b416264baff36b01f2ece0f4de14a58d0ff Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Thu, 12 Mar 2026 17:18:05 +0100 Subject: [PATCH 06/33] Updated Runmodem.md about the Dmod/Umod options --- doc/RUNMODEM.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index b747775860..a7e246b48e 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -464,7 +464,10 @@ sudo ./ran_build/build/nr-uesoftmodem -O ../targets/PROJECTS/GENERIC-NR-5GC/CONF The OAI UE can also be used in front of a OAI gNB without the support of eNB or EPC and circumventing random access. In this case both gNB and eNB need to be run with the `--phy-test` flag. At the gNB this flag does the following - it reads the RRC configuration from the configuration file - it encodes the RRCConfiguration and the RBconfig message and stores them in the binary files `rbconfig.raw` and `reconfig.raw` in the current directory - - the MAC uses a pre-configured allocation of PDSCH and PUSCH with randomly generated payload instead of the standard scheduler. The options `-m`, `-l`, `-t`, `-M`, `-T`, `-D`, and `-U` can be used to configure this scheduler. See `./nr-softmodem -h` for more information. + - the MAC uses a pre-configured allocation of PDSCH and PUSCH with randomly generated payload instead of the standard scheduler. The options `-m`, `-l`, `-t`, `-M`, `-T`, `-D`, and `-U` can be used to configure this scheduler. + - Options `-Dmod`, and `-Umod` were introduced to enable scheduling PDSCH/PUSCH on slots >= 64 in phy-test mode. (in case of >= 120Khz subcarrier spacing and FDD) + - For ex: `-Dmod 2' / '-Umod 2` allocates every 2nd slot for PDSCH or PUSCH respectively. + - See `./nr-softmodem -h` for more information. At the UE, the `--phy-test` flag will read the binary files `rbconfig.raw` and `reconfig.raw` from the current directory and process them. If you wish to provide a different path for these files, please use the options `--reconfig-file` and `--rbconfig-file`. From 9b7efe8e47078fc9f2f8e0e83ea2b4d594b1040f Mon Sep 17 00:00:00 2001 From: Mario Joa-Ng Date: Fri, 13 Mar 2026 22:11:46 +0100 Subject: [PATCH 07/33] handle start symbol on non-zeroth symbol for SIB for multiplexing pattern 3 configuration. --- radio/fhi_72/oaioran.c | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 617243b0fd..cf075cb9f0 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -543,7 +543,6 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) // Need to use --continuous-tx so that this routine will be triggered in RX slot. for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet. for (uint8_t ant_id = 0; ant_id < ru->nb_rx; ant_id++) { - int first = 1; // The first UL symbol const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf; // skip processing this slot is TX (no RX in this slot) if (!is_tdd_ul_guard_slot(frame_conf, slot)) { @@ -581,17 +580,10 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) pRbElm->nBeamIndex = 0; } } else { - if (first) { - // ant_id / no of antenna per beam gives the beam_nb - pRbElm->nBeamIndex = - ru->beam_id[ant_id / (ru->nb_rx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; - // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. - if (pRbElm->nBeamIndex == -1) { - pRbElm->nBeamIndex = 0; - } else { - first = 0; - } - } + // ant_id / no of antenna per beam gives the beam_nb + int16_t beam_id = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; + if (beam_id != -1) + pRbElm->nBeamIndex = beam_id; } } } @@ -663,13 +655,6 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) for (uint32_t idxElm = 0; idxElm < pPrbMap->nPrbElm; idxElm++) { struct xran_section_desc *p_sec_desc = NULL; struct xran_prb_elm *p_prbMapElm = &pPrbMap->prbMap[idxElm]; - if (sym_idx == 0) { - // ant_id / no of antenna per beam gives the beam_nb - p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT]; - // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. - if (p_prbMapElm->nBeamIndex == -1) - p_prbMapElm->nBeamIndex = 0; - } // radio-transport fragmentation is not supported in xran F release; // E-bit = 1 => each ethernet frame is considered as the last fragment; @@ -700,13 +685,10 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) if (p_prbMapElm->nBeamIndex == -1) p_prbMapElm->nBeamIndex = 0; } else { - if (sym_idx == 0) { - // ant_id / no of antenna per beam gives the beam_nb - p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT]; - // In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly. - if (p_prbMapElm->nBeamIndex == -1) - p_prbMapElm->nBeamIndex = 0; - } + // ant_id / no of antenna per beam gives the beam_nb + int16_t beam_id = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx]; + if ( beam_id != -1) + p_prbMapElm->nBeamIndex = beam_id; } dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); From 70711633bcf574f5bfbd507ff337bb2d586c9960 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Sun, 26 Oct 2025 23:13:59 +0100 Subject: [PATCH 08/33] code cleaning pss and sss detection, no functional change --- openair1/PHY/NR_REFSIG/sss_nr.h | 3 - openair1/PHY/NR_TRANSPORT/nr_sss.c | 13 +- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 6 +- .../PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/pss_nr.c | 188 +++------- openair1/PHY/NR_UE_TRANSPORT/sss_nr.c | 333 ++++-------------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 2 +- 7 files changed, 113 insertions(+), 434 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/sss_nr.h b/openair1/PHY/NR_REFSIG/sss_nr.h index 5bb55ebe2f..7bd37a7dc0 100644 --- a/openair1/PHY/NR_REFSIG/sss_nr.h +++ b/openair1/PHY/NR_REFSIG/sss_nr.h @@ -90,9 +90,6 @@ static const c16_t phase_nr[PHASE_HYPOTHESIS_NUMBER] = { void init_context_sss_nr(int amp); void free_context_sss_nr(void); -void insert_sss_nr(int16_t *sss_time, - NR_DL_FRAME_PARMS *frame_parms); - bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, int nid2, int target_Nid_cell, diff --git a/openair1/PHY/NR_TRANSPORT/nr_sss.c b/openair1/PHY/NR_TRANSPORT/nr_sss.c index 71bae9a065..08f7f86cbf 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sss.c +++ b/openair1/PHY/NR_TRANSPORT/nr_sss.c @@ -23,11 +23,7 @@ //#define NR_SSS_DEBUG -int nr_generate_sss( c16_t *txdataF, - int16_t amp, - uint8_t ssb_start_symbol, - nfapi_nr_config_request_scf_t* config, - NR_DL_FRAME_PARMS *frame_parms) +int nr_generate_sss(c16_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, int Nid, NR_DL_FRAME_PARMS *frame_parms) { int16_t x0[NR_SSS_LENGTH]; int16_t x1[NR_SSS_LENGTH]; @@ -35,7 +31,6 @@ int nr_generate_sss( c16_t *txdataF, const int x1_initial[7] = { 1, 0, 0, 0, 0, 0, 0 }; /// Sequence generation - int Nid = config->cell_config.phy_cell_id.value; int Nid2 = Nid % 3; int Nid1 = (Nid - Nid2)/3; @@ -59,13 +54,11 @@ int nr_generate_sss( c16_t *txdataF, /// Resource mapping // SSS occupies a predefined position (subcarriers 56-182, symbol 2) within the SSB block starting from - int k = frame_parms->ssb_start_subcarrier + 56; - int l = ssb_start_symbol + 2; + c16_t *tx = txdataF + (ssb_start_symbol + 2) * frame_parms->ofdm_symbol_size + frame_parms->ssb_start_subcarrier + 56; for (int i = 0; i < NR_SSS_LENGTH; i++) { int16_t d_sss = (1 - 2*x0[(i + m0) % NR_SSS_LENGTH] ) * (1 - 2*x1[(i + m1) % NR_SSS_LENGTH] ) * 23170; - ((int16_t*)txdataF)[2*(l*frame_parms->ofdm_symbol_size + k)] = (((int16_t)amp) * d_sss) >> 15; - k++; + *tx++ = (c16_t){.r = (amp * d_sss) >> 15}; } #ifdef NR_SSS_DEBUG // write_output("sss_0.m", "sss_0", (void*)txdataF[0][l*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index a38bf9b6bb..68b3842594 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -60,11 +60,7 @@ int nr_generate_pss(c16_t *txdataF, @param @returns 0 on success */ -int nr_generate_sss(c16_t *txdataF, - int16_t amp, - uint8_t ssb_start_symbol, - nfapi_nr_config_request_scf_t *config, - NR_DL_FRAME_PARMS *frame_parms); +int nr_generate_sss(c16_t *txdataF, int16_t amp, uint8_t ssb_start_symbol, int nid, NR_DL_FRAME_PARMS *frame_parms); /*! \fn void nr_generate_pbch_dmrs diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c index e407459bc8..0636c9d7d9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c @@ -260,7 +260,7 @@ static void sl_nr_extract_sss(PHY_VARS_NR_UE *ue, c16_t *sss = &sss_ext[0][0][0]; for (uint16_t id1 = 0; id1 < SL_NR_NUM_IDs_IN_SSS; id1++) { // all possible SSS Nid1 values - for (phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS + for (phase = 0; phase < sizeofArray(phase_nr); phase++) { // phase offset between PSS and SSS int32_t metric = 0, metric_re = 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index e4b68a4d66..2e142812e3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -49,24 +49,12 @@ //#define DBG_PSS_NR static time_stats_t generic_time[TIME_LAST]; -int pss_search_time_nr(const c16_t **rxdata, - const NR_DL_FRAME_PARMS *frame_parms, - const c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size], - bool fo_flag, - int is, - int target_Nid_cell, - int *nid2, - int *f_off, - int *pssPeak, - int *pssAvg, - int search_start, - int search_length); -static int16_t primary_synchro_nr2[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0}; +static int16_t d_pss[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0}; static c16_t primary_synchro[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0}; int16_t *get_primary_synchro_nr2(const int nid2) { - return primary_synchro_nr2[nid2]; + return d_pss[nid2]; } /******************************************************************* @@ -86,12 +74,9 @@ int16_t *get_primary_synchro_nr2(const int nid2) void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2) { AssertFatal(fp->ofdm_symbol_size > 127,"Illegal ofdm_symbol_size %d\n",fp->ofdm_symbol_size); - AssertFatal(N_ID_2>=0 && N_ID_2 <=2,"Illegal N_ID_2 %d\n",N_ID_2); - int16_t d_pss[LENGTH_PSS_NR]; + AssertFatal(N_ID_2 >= 0 && N_ID_2 <= 2, "Illegal N_ID_2 %d\n", N_ID_2); int16_t x[LENGTH_PSS_NR]; - int16_t *primary_synchro2 = primary_synchro_nr2[N_ID_2]; /* pss in complex with alternatively i then q */ - #define INITIAL_PSS_NR (7) const int16_t x_initial[INITIAL_PSS_NR] = {0, 1, 1, 0, 1, 1, 1}; assert(N_ID_2 < NUMBER_PSS_SEQUENCE); @@ -99,16 +84,15 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2) for (int i = 0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++) x[i + INITIAL_PSS_NR] = (x[i + 4] + x[i]) % (2); - + int16_t *pss = d_pss[N_ID_2]; for (int n=0; n < LENGTH_PSS_NR; n++) { const int m = (n + 43 * N_ID_2) % (LENGTH_PSS_NR); - d_pss[n] = 1 - 2*x[m]; + pss[n] = 1 - 2 * x[m]; } /* PSS is directly mapped to subcarrier without modulation 38.211 */ for (int i=0; i < LENGTH_PSS_NR; i++) { - primary_synchro[N_ID_2][i].r = (d_pss[i] * SHRT_MAX) >> SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */ - primary_synchro2[i] = d_pss[i]; + primary_synchro[N_ID_2][i].r = (pss[i] * SHRT_MAX) >> SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */ } #ifdef DBG_PSS_NR @@ -150,12 +134,13 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2) void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssbFirstSCS, c16_t pssTime[fp->ofdm_symbol_size]) { unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL; - unsigned int k = fp->first_carrier_offset + ssbFirstSCS + subcarrier_start; - if (k>= fp->ofdm_symbol_size) k-=fp->ofdm_symbol_size; c16_t synchroF_tmp[fp->ofdm_symbol_size] __attribute__((aligned(32))); memset(synchroF_tmp, 0, sizeof(synchroF_tmp)); + unsigned int k = fp->first_carrier_offset + ssbFirstSCS + subcarrier_start; for (int i=0; i < LENGTH_PSS_NR; i++) { - synchroF_tmp[k % fp->ofdm_symbol_size] = primary_synchro[N_ID_2][i]; + if (k >= fp->ofdm_symbol_size) + k -= fp->ofdm_symbol_size; + synchroF_tmp[k] = primary_synchro[N_ID_2][i]; k++; } @@ -182,54 +167,6 @@ void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssb } #endif - - - -#if 0 - -/* it allows checking that process of idft on a signal and then dft gives same signal with limited errors */ - - if ((N_ID_2 == 0) && (length == 256)) { - - LOG_M("pss_f00.m","pss_f00",synchro_tmp,length,1,1); - - - bzero(synchroF_tmp, size); - - - - /* get pss in the time domain by applying an inverse FFT */ - dft((int16_t)get_dft(length), - synchro_tmp, /* complex input */ - synchroF_tmp, /* complex output */ - 1); /* scaling factor */ - - if ((N_ID_2 == 0) && (length == 256)) { - LOG_M("pss_f_0.m","pss_f_0",synchroF_tmp,length,1,1); - } - - /* check Pss */ - k = length - (LENGTH_PSS_NR/2); - -#define LIMIT_ERROR_FFT (10) - - for (int i=0; i < LENGTH_PSS_NR; i++) { - if (abs(synchroF_tmp[2*k] - primary_synchro[i].r) > LIMIT_ERROR_FFT) { - printf("Pss Error[%d] Compute %d Reference %d \n", k, synchroF_tmp[2*k], primary_synchro[i].r); - } - - if (abs(synchroF_tmp[2*k+1] - primary_synchro[i].i) > LIMIT_ERROR_FFT) { - printf("Pss Error[%d] Compute %d Reference %d\n", (2*k+1), synchroF_tmp[2*k+1], primary_synchro[i].i); - } - - k++; - - if (k >= length) { - k-=length; - } - } - } -#endif } /******************************************************************* @@ -391,50 +328,32 @@ int pss_synchro_nr(const c16_t **rxdata, int *pssAvg) { #ifdef DBG_PSS_NR - - LOG_M("rxdata0_rand.m","rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], frame_parms->samples_per_frame, 1, 1); - -#endif - -#ifdef DBG_PSS_NR - - LOG_M("rxdata0_des.m","rxd0_des", &rxdata[0][0], frame_parms->samples_per_frame,1,1); - + LOG_M("rxdata0_rand.m", "rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], frame_parms->samples_per_frame, 1, 1); + LOG_M("rxdata0_des.m", "rxd0_des", &rxdata[0][0], frame_parms->samples_per_frame, 1, 1); #endif start_meas(&generic_time[TIME_PSS]); - int synchro_position = pss_search_time_nr(rxdata, frame_parms, pssTime, fo_flag, is, target_Nid_cell, nid2, f_off, pssPeak, pssAvg, -1, -1); + stop_meas(&generic_time[TIME_PSS]); #if TEST_SYNCHRO_TIMING_PSS - stop_meas(&generic_time[TIME_PSS]); - - int duration_ms = generic_time[TIME_PSS].p_time/(cpuf*1000.0); - - #ifndef NR_UNIT_TEST - - LOG_D(PHY,"PSS execution duration %4d microseconds \n", duration_ms); - - #endif - + int duration_ms = generic_time[TIME_PSS].p_time / (cpuf * 1000.0); +#ifndef NR_UNIT_TEST + LOG_D(PHY, "PSS execution duration %4d microseconds \n", duration_ms); +#endif #endif #ifdef SYNCHRO_DECIMAT - if (rate_change != 1) { - if (rxdata[0] != NULL) { - for (int aa=0;aanb_antennas_rx;aa++) { free(rxdata[aa]); } - free(rxdata); } - - restore_frame_context_pss_nr(frame_parms, rate_change); + restore_frame_context_pss_nr(frame_parms, rate_change); } #endif @@ -504,11 +423,6 @@ int pss_search_time_nr(const c16_t **rxdata, int search_start, int search_length) { - unsigned int n, ar, peak_position, pss_source; - int64_t peak_value; - int64_t avg[NUMBER_PSS_SEQUENCE] = {0}; - double ffo_est = 0; - // Determine search window unsigned int start, length; if (search_start >= 0 && search_length > 0) { @@ -524,11 +438,7 @@ int pss_search_time_nr(const c16_t **rxdata, length = frame_parms->samples_per_frame; } - AssertFatal(length>0,"illegal length %d\n",length); - peak_value = 0; - peak_position = 0; - pss_source = 0; - + AssertFatal(length > 0, "illegal length %d\n", length); int maxval=0; int max_size = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; for (int j = 0; j < max_size; j++) @@ -542,53 +452,55 @@ int pss_search_time_nr(const c16_t **rxdata, /* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */ /* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */ - uint16_t pss_index_start = 0; - uint16_t pss_index_end = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; + int pss_index_start; + int pss_index_end; if (target_Nid_cell != -1) { pss_index_start = GET_NID2(target_Nid_cell); pss_index_end = pss_index_start + 1; + } else { + pss_index_start = 0; + pss_index_end = max_size; } + int64_t avg[NUMBER_PSS_SEQUENCE] = {0}; + int64_t peak_value = 0; + unsigned int peak_position = 0; + unsigned int pss_source = 0; for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) { - for (n = start; n < start + length; n += 4) { // - - int64_t pss_corr_ue=0; + for (int n = start; n < start + length; n += 4) { // + int64_t pss_corr_ue = 0; /* calculate dot product of primary_synchro_time_nr and rxdata[ar][n] * (ar=0..nb_ant_rx) and store the sum in temp[n]; */ - for (ar=0; arnb_antennas_rx; ar++) { - + for (int ar = 0; ar < frame_parms->nb_antennas_rx; ar++) { /* perform correlation of rx data and pss sequence ie it is a dot product */ const c32_t result = dot_product(pssTime[pss_index], - &(rxdata[ar][n + is * frame_parms->samples_per_frame]), + &rxdata[ar][n + is * frame_parms->samples_per_frame], frame_parms->ofdm_symbol_size, shift); const c64_t r64 = {.r = result.r, .i = result.i}; pss_corr_ue += squaredMod(r64); - //((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */ - //((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */ - //((short*)&synchro_out)[0] += ((int*) &result)[0]; /* real part */ - //((short*)&synchro_out)[1] += ((int*) &result)[1]; /* imaginary part */ - } - + /* calculate the absolute value of sync_corr[n] */ - avg[pss_index]+=pss_corr_ue; + avg[pss_index] += pss_corr_ue; if (pss_corr_ue > peak_value) { peak_value = pss_corr_ue; peak_position = n; pss_source = pss_index; - + #ifdef DEBUG_PSS_NR printf("pss_index %d: n %6u peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_ue[n]); #endif } } + avg[pss_index] /= (length / 4); } - - if (fo_flag){ - // fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS - // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012. + double ffo_est = 0; + if (fo_flag) { + // fractional frequency offset computation according to Cross-correlation Synchronization Algorithm Using PSS + // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th + // International Conference on Communications and Networking in China, 2012. // Computing cross-correlation at peak on half the symbol size for first half of data c32_t r1 = dot_product(pssTime[pss_source], @@ -606,15 +518,11 @@ int pss_search_time_nr(const c16_t **rxdata, ffo_est = atan2(r1d.r * r2d.i - r2d.r * r1d.i, r1d.r * r2d.r + r1d.i * r2d.i) / M_PI; #ifdef DBG_PSS_NR - printf("ffo %lf\n",ffo_est); + printf("ffo %lf\n", ffo_est); #endif } - // computing absolute value of frequency offset - *f_off = ffo_est*frame_parms->subcarrier_spacing; - - for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) - avg[pss_index] /= (length / 4); + *f_off = ffo_est * frame_parms->subcarrier_spacing; *nid2 = pss_source; *pssPeak = dB_fixed64(peak_value); @@ -631,22 +539,18 @@ int pss_search_time_nr(const c16_t **rxdata, ffo_est); if ((search_start < 0 || search_length == 0) && peak_value < 5 * avg[pss_source]) - return(-1); - + return (-1); #ifdef DBG_PSS_NR - static int debug_cnt = 0; - if (debug_cnt == 0) { if (is) - LOG_M("rxdata1.m","rxd0",rxdata[frame_parms->samples_per_frame],length,1,1); + LOG_M("rxdata1.m", "rxd0", rxdata[frame_parms->samples_per_frame], length, 1, 1); else - LOG_M("rxdata0.m","rxd0",rxdata[0],length,1,1); + LOG_M("rxdata0.m", "rxd0", rxdata[0], length, 1, 1); } else { debug_cnt++; } - #endif return peak_position; diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 34751c1742..8e9c3ad510 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -109,71 +109,8 @@ void init_context_sss_nr(int amp) #endif } -/******************************************************************* -* -* NAME : insert_sss_nr -* -* PARAMETERS : pointer to input buffer for which sss in inserted -* amp amplitude applied to input -* frame parameters for cell identity -* -* RETURN : none -* -* DESCRIPTION : Allow to generate a reference sss sequence according to cell identity -* -*********************************************************************/ - -//#define DEBUG_SSS_NR -//#define DEBUG_PLOT_SSS -void insert_sss_nr(int16_t *sss_time, - NR_DL_FRAME_PARMS *frame_parms) -{ - const unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size; - int Nid2 = GET_NID2(frame_parms->Nid_cell); - int Nid1 = GET_NID1(frame_parms->Nid_cell); - - /* call of IDFT should be done with ordered input as below - * - * n input samples - * <------------------------------------------------> - * 0 n - * are written into input buffer for IFFT in this order - * ------------------------------------------------- - * |xxxxxxx N/2 xxxxxxxx| - * -------------------------------------------------- - * ^ ^ ^ ^ ^ - * | | | | | - * n/2 end of n=0 start of n/2-1 - * sss sss - * - * Frequencies - * positives negatives - * 0 (+N/2)(-N/2) - * |-----------------------><-------------------------| - * - * sample 0 is for continuous frequency which is not used here - */ - - unsigned int k = ofdm_symbol_size - ((LENGTH_SSS_NR/2)+1); - c16_t synchroF_tmp[2048] __attribute__((aligned(32))); - c16_t synchro_tmp[2048] __attribute__((aligned(32))); - bzero(synchroF_tmp, sizeof(synchroF_tmp)); - - /* SSS is directly mapped to subcarrier */ - for (int i=0; inb_antennas_rx][LENGTH_PSS_NR], c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR]) @@ -199,148 +136,60 @@ static int pss_ch_est_nr(const NR_DL_FRAME_PARMS *frame_parms, c16_t *pss_ext2 = pss_ext[aarx]; for (int i = 0; i < LENGTH_PSS_NR; i++) { // This is H*(PSS) = R* \cdot PSS - const int tmp_re = pss_ext2[i].r * pss[i]; - const int tmp_im = -pss_ext2[i].i * pss[i]; - - const int32_t amp = tmp_re * tmp_re + tmp_im * tmp_im; + const c16_t tmp = (c16_t){pss_ext2[i].r * pss[i], -pss_ext2[i].i * pss[i]}; + const int32_t amp = squaredMod(tmp); const int shift = log2_approx(amp) / 2; // This is R(SSS) \cdot H*(PSS) - const c16_t tmp = {(tmp_re * sss_ext2[i].r - tmp_im * sss_ext2[i].i) >> shift, - (tmp_re * sss_ext2[i].i + tmp_im * sss_ext2[i].r) >> shift}; - // printf("SSSi(%d,%d) : (%d,%d)\n",aarx,i,sss_ext2[i<<1],sss_ext2[1+(i<<1)]); - // printf("SSSo(%d,%d) : (%d,%d)\n",aarx,i,tmp_re2,tmp_im2); - // MRC on RX antennas - if (aarx == 0) { - sss_ext2[i].r = tmp.r; - sss_ext2[i].i = tmp.i; - } else { - sss_ext2[i].r += tmp.r; - sss_ext2[i].i += tmp.i; - } + const c16_t new_sss = c16mulShift(tmp, sss_ext2[i], shift); + if (aarx == 0) + sss_ext2[i] = new_sss; + else + sss_ext2[i] = c16add(sss_ext2[i], new_sss); } } -#if 0 - LOG_M("pssrx.m","pssrx",pss,LENGTH_PSS_NR,1,1); - LOG_M("pss_ext.m","pssext",pss_ext2,LENGTH_PSS_NR,1,1); - LOG_M("psschest.m","pssch",chest,LENGTH_PSS_NR,1,1); -#endif -#if 0 - - for (int i = 0; i < LENGTH_PSS_NR; i++) { - printf(" sss ext 2 [%d] %d %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1]); - printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i]); - printf(" sss ext 3 [%d] %d %d at address %p\n", i, sss_ext3[2*i], sss_ext3[2*i+1]); - } - -#endif - - // sss_ext now contains the compensated SSS - return(0); + // sss_ext[0] now contains the compensated SSS } /******************************************************************* -* -* NAME : do_pss_sss_extract -* -* PARAMETERS : none -* -* RETURN : none -* -* DESCRIPTION : it allows extracting sss from samples buffer -* -*********************************************************************/ + * + * NAME : pss_sss_extract_nr + * + * PARAMETERS : none + * + * RETURN : none + * + * DESCRIPTION : it allows extracting sss from samples buffer + * + *********************************************************************/ -static int do_pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms, +static void pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms, c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR], c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR], - uint8_t doPss, - uint8_t doSss, int ssb_start_subcarrier, c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both { - AssertFatal(frame_parms->nb_antennas_rx > 0, "UB as sss_ext is not set to any value\n"); + AssertFatal(frame_parms->nb_antennas_rx > 0, "nb antennas as sss_ext is not set to any value\n"); + const unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size; + const int pss_symbol = 0; + const int sss_symbol = + get_softmodem_params()->sl_mode == 0 ? (SSS_SYMBOL_NB - PSS_SYMBOL_NB) : (SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB); for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - int pss_symbol = 0; - int sss_symbol = get_softmodem_params()->sl_mode == 0 ? - (SSS_SYMBOL_NB - PSS_SYMBOL_NB) : - (SSS0_SL_SYMBOL_NB - PSS0_SL_SYMBOL_NB) ; - unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size; - c16_t *pss_rxF = rxdataF[aarx] + pss_symbol * ofdm_symbol_size; c16_t *sss_rxF = rxdataF[aarx] + sss_symbol * ofdm_symbol_size; - c16_t *pss_rxF_ext = pss_ext[aarx]; c16_t *sss_rxF_ext = sss_ext[aarx]; - unsigned int k = frame_parms->first_carrier_offset + ssb_start_subcarrier + ((get_softmodem_params()->sl_mode == 0) ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL); - if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; - for (int i=0; i < LENGTH_PSS_NR; i++) { - if (doPss) { - pss_rxF_ext[i] = pss_rxF[k]; - } - - if (doSss) { - sss_rxF_ext[i] = sss_rxF[k]; - } - + if (k >= frame_parms->ofdm_symbol_size) + k -= frame_parms->ofdm_symbol_size; + pss_rxF_ext[i] = pss_rxF[k]; + sss_rxF_ext[i] = sss_rxF[k]; k++; - if (k == frame_parms->ofdm_symbol_size) k = 0; } } - -#if 0 - - int16_t *p = (int16_t *)sss_rxF_ext; - - for (int i = 0; i < LENGTH_PSS_NR; i++) { - printf(" sss ext 2 [%d] %d %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]); - printf(" sss ref [%d] %d %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]); - } - -#endif - -#if 0 - - int16_t *p2 = (int16_t *)pss_rxF_ext; - - for (int i = 0; i < LENGTH_PSS_NR; i++) { - printf(" pss_rxF_ext [%d] %d %d at address %p\n", i, p2[2*i], p2[2*i+1], &p2[2*i]); - } - -#endif - - return(0); -} - -/******************************************************************* -* -* NAME : pss_sss_extract_nr -* -* PARAMETERS : none -* -* RETURN : none -* -* DESCRIPTION : -* -*********************************************************************/ - -static int pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms, - c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR], - c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR], - int ssb_start_subcarrier, - c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) -{ - return do_pss_sss_extract_nr(frame_parms, - pss_ext, - sss_ext, - 1 /* doPss */, - 1 /* doSss */, - ssb_start_subcarrier, - rxdataF); } /******************************************************************* @@ -366,44 +215,22 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, int *freq_offset_sss, c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) { - uint8_t i; c16_t pss_ext[frame_parms->nb_antennas_rx][LENGTH_PSS_NR]; c16_t sss_ext[frame_parms->nb_antennas_rx][LENGTH_SSS_NR]; - uint8_t Nid2 = GET_NID2(nid2); - uint16_t Nid1; - uint8_t phase; - int32_t metric, metric_re; - int16_t *d; - + const int Nid2 = GET_NID2(nid2); // pss sss extraction pss_sss_extract_nr(frame_parms, pss_ext, sss_ext, ssb_start_subcarrier, rxdataF); /* subframe */ #ifdef DEBUG_PLOT_SSS - write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_subframe,1,1); write_output("rxdataF0_pss.m","rxF0_pss",&ue->common_vars.rxdataF[0][0],frame_parms->ofdm_symbol_size,1,1); write_output("rxdataF0_sss.m","rxF0_sss",&ue->common_vars.rxdataF[0][(SSS_SYMBOL_NB-PSS_SYMBOL_NB)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size,1,1); - write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1); - -#endif - -#if 0 - int16_t *p = (int16_t *)sss_ext[0]; - int16_t *p2 = (int16_t *)pss_ext[0]; - - for (int i = 0; i < LENGTH_SSS_NR; i++) { - printf("sss ref [%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]); - printf("sss ext [%i] : %d %d \n", i, p[2*i], p[2*i+1]); - - printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]); - printf("pss ext [%i] : %d %d \n", i, p2[2*i], p2[2*i+1]); - } + write_output("pss_ext.m", "pss_ext", pss_ext, LENGTH_PSS_NR, 1, 1); #endif // get conjugated channel estimate from PSS, H* = R* \cdot PSS // and do channel estimation and compensation based on PSS - pss_ch_est_nr(frame_parms, nid2, pss_ext, sss_ext); // now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.h @@ -411,91 +238,49 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, c16_t *sss = sss_ext[0]; -#ifdef DEBUG_PLOT_SSS - - write_output("sss_ext.m","sss_ext",sss_ext[0],LENGTH_SSS_NR,1,1); - write_output("sss_ref.m","sss_ref", d_sss,LENGTH_SSS_NR,1,1); - -#endif - - -#if 0 - - /* simulate of a phase shift on the signal */ - - int phase_shift_index = 0; - - phase_shift_samples(sss, LENGTH_SSS_NR, phase_re_nr[phase_shift_index], phase_im_nr[phase_shift_index]); - -#endif - -#if 0 - int16_t *ps = (int16_t *)pss_ext; - - for (int i = 0; i < LENGTH_SSS_NR; i++) { - printf("sss ref [%i] : %d \n", i, d_sss[0][0][i]); - printf("sss ext [%i] : %d %d \n", i, sss[i].r, sss[i].i); - - printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr2[0][2*i], primary_synchro_nr2[0][2*i+1]); - printf("pss ext [%i] : %d %d \n", i, ps[2*i], ps[2*i+1]); - } -#endif - /* for phase evaluation, one uses an array of possible phase shifts */ /* then a correlation is done between received signal with a shift pĥase and the reference signal */ /* Computation of signal with shift phase is based on below formula */ /* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */ /* sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */ - uint16_t Nid1_start = 0; - uint16_t Nid1_end = N_ID_1_NUMBER; + int Nid1_start = 0; + int Nid1_end = N_ID_1_NUMBER; if (target_Nid_cell != -1) { Nid1_start = GET_NID1(target_Nid_cell); Nid1_end = Nid1_start + 1; } - for (Nid1 = Nid1_start; Nid1 < Nid1_end; Nid1++) { // all possible Nid1 values - for (phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS - - metric = 0; - metric_re = 0; - - d = (int16_t *)&d_sss[Nid2][Nid1]; - + for (int n1 = Nid1_start; n1 < Nid1_end; n1++) { // all possible Nid1 values + for (int phase = 0; phase < sizeofArray(phase_nr); phase++) { // phase offset between PSS and SSS + int64_t metric = 0; + int16_t *d = d_sss[Nid2][n1]; // This is the inner product using one particular value of each unknown parameter - for (i=0; i < LENGTH_SSS_NR; i++) { - metric_re += d[i] * ((phase_nr[phase].r * sss[i].r - phase_nr[phase].i * sss[i].i) >> SCALING_METRIC_SSS_NR); + for (int i = 0; i < LENGTH_SSS_NR; i++) { + metric += d[i] * (phase_nr[phase].r * sss[i].r - phase_nr[phase].i * sss[i].i); } - - metric = metric_re; - + metric >>= SCALING_METRIC_SSS_NR; // if the current metric is better than the last save it if (metric > *tot_metric) { *tot_metric = metric; - *Nid_cell = Nid2 + (3 * Nid1); + *Nid_cell = Nid2 + (3 * n1); *phase_max = phase; #ifdef DEBUG_SSS_NR - - LOG_D(PHY,"(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max); - + LOG_D(PHY, + "(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n", + phase, + n1, + metric, + *tot_metric, + *phase_max); #endif } } } -//#ifdef DEBUG_SSS_NR #define SSS_METRIC_FLOOR_NR (30000) - if (*tot_metric > SSS_METRIC_FLOOR_NR) { - Nid2 = GET_NID2(*Nid_cell); - Nid1 = GET_NID1(*Nid_cell); - LOG_D(PHY,"Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max); - } -// #endif - - int re = 0; - int im = 0; - if (Nid1 == Nid1_end) { + if (*tot_metric < SSS_METRIC_FLOOR_NR) { LOG_D(PHY, "Failed to detect SSS after PSS, metric of SSS %d, threshold to consider SSS valid %d, detected PCI: %d\n", *tot_metric, @@ -503,15 +288,19 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, *Nid_cell); return false; } - d = (int16_t *)&d_sss[Nid2][Nid1]; - for(i = 0; isubcarrier_spacing); - double ffo_pss = ((double)freq_offset_pss) / frame_parms->subcarrier_spacing; + double ffo_pss = (double)freq_offset_pss / frame_parms->subcarrier_spacing; LOG_D(NR_PHY, "SSS detected, PCI: %d, ffo_pss %f (%i Hz), ffo_sss %f (%i Hz), ffo_pss+ffo_sss %f (%i Hz), nid1: %d, nid2: %d\n", *Nid_cell, diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 97ad60cfff..46be5a18cc 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -156,7 +156,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n bitmap); nr_generate_pss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp); - nr_generate_sss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp); + nr_generate_sss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg->cell_config.phy_cell_id.value, fp); uint16_t slots_per_hf = (fp->slots_per_frame) >> 1; int n_hf = slot < slots_per_hf ? 0 : 1; From e151366beaa5d6a082c2624a455263ff8c7b28c2 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Mon, 27 Oct 2025 21:42:56 +0100 Subject: [PATCH 09/33] SSS detection used PSS phase, but when signal is noisy, use the PSS phase can make a SSS slightly rotated the code use a precomputed table of rotations: 16 steaps between -PI/3 and +PI/3 This commit replaces the precomputed table by in code computation. This version improves code understanding, while it won't make any significant difference --- openair1/PHY/NR_REFSIG/sss_nr.h | 26 ------------------- .../PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c | 8 +++--- openair1/PHY/NR_UE_TRANSPORT/sss_nr.c | 19 +++++++++----- 3 files changed, 17 insertions(+), 36 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/sss_nr.h b/openair1/PHY/NR_REFSIG/sss_nr.h index 7bd37a7dc0..ae99a8e3d4 100644 --- a/openair1/PHY/NR_REFSIG/sss_nr.h +++ b/openair1/PHY/NR_REFSIG/sss_nr.h @@ -61,32 +61,6 @@ #define SSS_METRIC_FLOOR_NR (30000) -/************** VARIABLES *****************************************/ - -#define PHASE_HYPOTHESIS_NUMBER (16) -#define INDEX_NO_PHASE_DIFFERENCE (3) /* this is for no phase shift case */ - -/************** FUNCTION ******************************************/ - -static const c16_t phase_nr[PHASE_HYPOTHESIS_NUMBER] = { - // {pi/3 ---- pi/3, -pi/3 ---- pi/3} - {16384, -28377}, - {20173, -25821}, - {23571, -22762}, - {26509, -19260}, - {28932, -15383}, - {30791, -11207}, - {32051, -6813}, - {32687, -2286}, - {32687, 2286}, - {32051, 6813}, - {30791, 11207}, - {28932, 15383}, - {26509, 19260}, - {23571, 22762}, - {20173, 25821}, - {16384, 28377}}; - void init_context_sss_nr(int amp); void free_context_sss_nr(void); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c index 0636c9d7d9..00506ef419 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c @@ -161,7 +161,6 @@ static void sl_nr_extract_sss(PHY_VARS_NR_UE *ue, NR_DL_FRAME_PARMS *sl_fp = &ue->SL_UE_PHY_PARAMS.sl_frame_params; int16_t *d; uint16_t Nid1 = 0; - uint8_t phase; c16_t *rxF_ext; for (int aarx = 0; aarx < sl_fp->nb_antennas_rx; aarx++) { @@ -260,15 +259,16 @@ static void sl_nr_extract_sss(PHY_VARS_NR_UE *ue, c16_t *sss = &sss_ext[0][0][0]; for (uint16_t id1 = 0; id1 < SL_NR_NUM_IDs_IN_SSS; id1++) { // all possible SSS Nid1 values - for (phase = 0; phase < sizeofArray(phase_nr); phase++) { // phase offset between PSS and SSS + for (int phase = -15; phase < 16; phase += 2) { // phase offset between PSS and SSS int32_t metric = 0, metric_re = 0; - + const c64_t rot = (c64_t){round(cos(M_PI / 3 / 15 * (phase)) * 32767), round(sin(M_PI / 3 / 15 * (phase)) * 32767)}; d = (int16_t *)&ue->SL_UE_PHY_PARAMS.init_params.sl_sss_for_sync[Nid2 * SL_NR_NUM_IDs_IN_SSS + id1]; // This is the inner product using one particular value of each unknown parameter for (int i = 0; i < SL_NR_SSS_SEQUENCE_LENGTH; i++) { - metric_re += d[i] * (((int64_t)phase_nr[phase].r * sss[i].r - phase_nr[phase].i * sss[i].i) >> 15); + // metric is only real part because sss is a pure real signal (imaginary is 0) + metric_re += d[i] * ((rot.r * sss[i].r - rot.i * sss[i].i) >> 15); } metric = metric_re; diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 8e9c3ad510..d400369bb1 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -251,20 +251,23 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, Nid1_end = Nid1_start + 1; } - for (int n1 = Nid1_start; n1 < Nid1_end; n1++) { // all possible Nid1 values - for (int phase = 0; phase < sizeofArray(phase_nr); phase++) { // phase offset between PSS and SSS + const int phase_to_try[] = {0, 2, -2, 4, -4, 6, -6, 8, -8, 10, -10, 12, -12, 14, -14}; + for (int idx = 0; idx < sizeofArray(phase_to_try); idx++) { // phase offset between PSS and SSS + const c64_t rot = + (c64_t){round(cos(M_PI / 3 / 15 * (phase_to_try[idx])) * 32767), round(sin(M_PI / 3 / 15 * (phase_to_try[idx])) * 32767)}; + for (int n1 = Nid1_start; n1 < Nid1_end; n1++) { // all possible Nid1 values int64_t metric = 0; int16_t *d = d_sss[Nid2][n1]; - // This is the inner product using one particular value of each unknown parameter for (int i = 0; i < LENGTH_SSS_NR; i++) { - metric += d[i] * (phase_nr[phase].r * sss[i].r - phase_nr[phase].i * sss[i].i); + // metric is only real part because sss is a pure real signal (imaginary is 0) + metric += d[i] * (rot.r * sss[i].r - rot.i * sss[i].i); } metric >>= SCALING_METRIC_SSS_NR; // if the current metric is better than the last save it if (metric > *tot_metric) { *tot_metric = metric; *Nid_cell = Nid2 + (3 * n1); - *phase_max = phase; + *phase_max = idx; #ifdef DEBUG_SSS_NR LOG_D(PHY, @@ -277,9 +280,13 @@ bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, #endif } } + // we try progressively rotation between pss and sss + // but pss and sss are in phase at emission + // rotation means doppler variation, or very noisy pss detection + if (*tot_metric >= SSS_METRIC_FLOOR_NR) + break; } -#define SSS_METRIC_FLOOR_NR (30000) if (*tot_metric < SSS_METRIC_FLOOR_NR) { LOG_D(PHY, "Failed to detect SSS after PSS, metric of SSS %d, threshold to consider SSS valid %d, detected PCI: %d\n", From 246e2ed31d125ee5f7bb50bc5f022adc76b4f174 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 27 Feb 2026 12:19:10 +0100 Subject: [PATCH 10/33] replace static allocation of max antennas in a dynamic structure for gnb rach --- executables/nr-ru.c | 5 ++- openair1/PHY/NR_TRANSPORT/nr_prach.c | 44 +++++++++++------- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 2 +- .../PHY/NR_UE_ESTIMATION/nr_ue_measurements.c | 24 +++------- openair1/PHY/defs_nr_common.h | 4 +- openair1/SCHED_NR/nr_prach_procedures.c | 2 +- openair1/SIMULATION/NR_PHY/prachsim.c | 45 +++++++++++-------- radio/fhi_72/oaioran.c | 2 +- radio/fhi_72/oran_isolate.c | 4 +- radio/fhi_72/oran_isolate.h | 3 +- 10 files changed, 71 insertions(+), 64 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 1d1b3ca014..4dd7a23d39 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -998,9 +998,10 @@ void *ru_thread(void *param) proc->tti_rx * gNB->frame_parms.samples_per_slot_wCP); // Do PRACH RU processing - prach_item_t *p = find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, SEARCH_EXIST); + prach_item_t *p = + find_nr_prach(&gNB->prach_list, proc->frame_rx, proc->tti_rx, gNB->frame_parms.nb_antennas_rx, SEARCH_EXIST); if (p) { - // need to extract RACH data for lqter processing by rx_nr_prach() + // need to extract RACH data for later processing by rx_nr_prach() rx_nr_prach_ru(p, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); } // end if (prach_id >= 0) } // end if (ru->feprx) diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 7b306e547a..f5d7740a69 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -39,8 +39,7 @@ void init_prach_list(prach_list_t *l) { pthread_mutex_init(&l->prach_list_mutex, NULL); - for (prach_item_t *p = l->list; p < l->list + NUMBER_OF_NR_PRACH_MAX; p++) - *p = (prach_item_t){.frame = -1, .slot = -1}; + memset(l->list, 0, sizeof(l->list)); } void free_nr_prach_entry(prach_list_t *l, prach_item_t *p) @@ -48,17 +47,18 @@ void free_nr_prach_entry(prach_list_t *l, prach_item_t *p) pthread_mutex_lock(&l->prach_list_mutex); if (p->frame == -1) LOG_E(NR_PHY_RACH, "Freeing a not allocated prach entry\n"); - *p = (prach_item_t){.frame = -1, .slot = -1, .num_slots = -1}; + *p = (prach_item_t){.frame = -1, .slot = -1, .num_slots = -1, .nb_rx = p->nb_rx, .prach_buf = (void *)(p + 1)}; pthread_mutex_unlock(&l->prach_list_mutex); } -prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, find_type_t type) +prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, int nb_rx, find_type_t type) { pthread_mutex_lock(&l->prach_list_mutex); - prach_item_t *p = l->list; - prach_item_t *end = p + NUMBER_OF_NR_PRACH_MAX; + AssertFatal(nb_rx, "Error! Number of antennas set to 0.\n"); + prach_item_t **p = l->list; + prach_item_t **end = p + NUMBER_OF_NR_PRACH_MAX; for (; p < end; p++) - if (p->frame == frame && (p->slot + p->num_slots - 1) == slot) + if ((*p) && (*p)->frame == frame && ((*p)->slot + (*p)->num_slots - 1) == slot) break; if (p == end) { if (type == SEARCH_EXIST) { @@ -66,7 +66,7 @@ prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, find_type_t ty return NULL; } for (p = l->list; p < end; p++) - if (p->frame == -1 && p->slot == -1) + if (!(*p) || ((*p)->frame == -1 && (*p)->slot == -1)) break; } if (p == end) { @@ -74,14 +74,24 @@ prach_item_t *find_nr_prach(prach_list_t *l, int frame, int slot, find_type_t ty return NULL; } // mark it used, it will be filled later - p->frame = frame; + if (*p && (*p)->nb_rx != nb_rx) { + LOG_W(PHY, "rach procedure nb_rx ant changed from %d to %d\n", (*p)->nb_rx, nb_rx); + free(*p); + *p = NULL; + } + if (!(*p)) { + *p = calloc(1, sizeof(prach_item_t) + sizeof(c16_t) * nb_rx * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L); + (*p)->prach_buf = (void *)((*p) + 1); + } + (*p)->nb_rx = nb_rx; + (*p)->frame = frame; pthread_mutex_unlock(&l->prach_list_mutex); - return p; + return (*p); } prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) { - prach_item_t *prach = find_nr_prach(&gNB->prach_list, SFN, Slot, SEARCH_EXIST_OR_FREE); + prach_item_t *prach = find_nr_prach(&gNB->prach_list, SFN, Slot, gNB->frame_parms.nb_antennas_rx, SEARCH_EXIST_OR_FREE); if (!prach) { LOG_W(PHY, "no free space for a new detected rach, discarding\n"); return NULL; @@ -380,7 +390,7 @@ static void rx_nr_prach_ru_internal(prach_item_t *p, rxsigF_tmp[j] = c16add(rxsigF_tmp[j], tmp[k2]); } } - memcpy(p->rxsigF[prachOccasion][aa], rxsigF_tmp, sizeof(rxsigF_tmp)); + memcpy(p->prach_buf[aa][prachOccasion], rxsigF_tmp, sizeof(rxsigF_tmp)); } } @@ -444,7 +454,7 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *in, int occasion) int32_t prach_ifft[dft_sz] __attribute__((aligned(32))); for (int preamble_index = 0; preamble_index < 64; preamble_index++) { if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - int en = dB_fixed(signal_energy((int32_t *)in->rxsigF[occasion][0], N_ZC == 839 ? 840 : 140)); + int en = dB_fixed(signal_energy((int32_t *)in->prach_buf[0][occasion], N_ZC == 839 ? 840 : 140)); if (en > 60) LOG_D(PHY, "frame %d, slot %d : Trying preamble %d \n", in->frame, in->slot, preamble_index); } @@ -520,7 +530,7 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *in, int occasion) // Compute DFT of RX signal (conjugate in->rxsigF[occasion], results in conjugate output) for each new rootSequenceIndex if (LOG_DEBUGFLAG(DEBUG_PRACH)) { - int en = dB_fixed(signal_energy((int32_t *)in->rxsigF[occasion][0], 840)); + int en = dB_fixed(signal_energy((int32_t *)in->prach_buf[0][occasion], 840)); if (en>60) LOG_D(PHY, "frame %d, slot %d : preamble index %d, NCS %d, N_ZC/NCS %d: offset %d, preamble shift %d , en %d)\n", @@ -549,14 +559,14 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *in, int occasion) memset(prach_ifft, 0, sizeof(prach_ifft)); if (LOG_DUMPFLAG(DEBUG_PRACH)) { - LOG_M("prach_rxF0.m", "prach_rxF0", in->rxsigF[occasion][0], N_ZC, 1, 1); - LOG_M("prach_rxF1.m", "prach_rxF1", in->rxsigF[occasion][1], 6144, 1, 1); + LOG_M("prach_rxF0.m", "prach_rxF0", in->prach_buf[0][occasion], N_ZC, 1, 1); + LOG_M("prach_rxF1.m", "prach_rxF1", in->prach_buf[1][occasion], 6144, 1, 1); } c16_t prachF[dft_sz] __attribute__((aligned(32))); for (int aa = 0; aa < nb_rx; aa++) { // Do componentwise product with Xu* on each antenna for (int offset = 0; offset < N_ZC; offset++) { - prachF[offset] = c16MulConjShift(Xu[offset], in->rxsigF[occasion][aa][offset], 15); + prachF[offset] = c16MulConjShift(Xu[offset], in->prach_buf[aa][occasion][offset], 15); } memset(prachF + N_ZC, 0, sizeof(*prachF) * (dft_sz - N_ZC)); // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index a38bf9b6bb..ca694ca53b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -206,7 +206,7 @@ rx_prach_out_t rx_nr_prach(const prach_item_t *, int occasion); void rx_nr_prach_ru(prach_item_t *, int32_t **, NR_DL_FRAME_PARMS *frame_parms, int N_TA_offset); -prach_item_t *find_nr_prach(prach_list_t *, int frame, int slot, find_type_t type); +prach_item_t *find_nr_prach(prach_list_t *, int frame, int slot, int nb_rx, find_type_t type); void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 5190bbf83d..92a020dc6c 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -147,37 +147,25 @@ uint32_t nr_ue_calculate_ssb_rsrp(const NR_DL_FRAME_PARMS *fp, int symbol_offset, int ssb_start_subcarrier) { - int k_start = 56; - int k_end = 183; - unsigned int ssb_offset = fp->first_carrier_offset + ssb_start_subcarrier; - - uint8_t l_sss = (symbol_offset + 2) % fp->symbols_per_slot; - + const int k_start = 56; + const int k_end = 183; + const unsigned int ssb_offset = fp->first_carrier_offset + ssb_start_subcarrier; + const uint8_t l_sss = (symbol_offset + 2) % fp->symbols_per_slot; uint32_t rsrp = 0; LOG_D(PHY, "In %s: l_sss %d ssb_offset %d\n", __FUNCTION__, l_sss, ssb_offset); int nb_re = 0; - for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) { - int16_t *rxF_sss = (int16_t *)&rxdataF[aarx][l_sss * fp->ofdm_symbol_size]; - + const c16_t *rxF_sss = &rxdataF[aarx][l_sss * fp->ofdm_symbol_size]; for(int k = k_start; k < k_end; k++){ int re = (ssb_offset + k) % fp->ofdm_symbol_size; - -#ifdef DEBUG_MEAS_UE - LOG_I(PHY, "In %s rxF_sss[%d] %d %d\n", __FUNCTION__, re, rxF_sss[re * 2], rxF_sss[re * 2 + 1]); -#endif - - rsrp += (((int32_t)rxF_sss[re*2]*rxF_sss[re*2]) + ((int32_t)rxF_sss[re*2 + 1]*rxF_sss[re*2 + 1])); + rsrp += squaredMod(rxF_sss[re]); nb_re++; - } } rsrp /= nb_re; - LOG_D(PHY, "In %s: RSRP/nb_re: %d nb_re :%d\n", __FUNCTION__, rsrp, nb_re); - return rsrp; } diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 4b6737a4ed..3906a7efce 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -141,14 +141,14 @@ typedef struct { int restricted_set; int numerology_index; int nb_rx; - c16_t rxsigF[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NB_ANTENNAS_RX][NR_PRACH_SEQ_LEN_L]; c16_t (*Xu)[839]; time_stats_t *rx_prach; + c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L]; } prach_item_t; typedef struct { /// prach commands - prach_item_t list[NUMBER_OF_NR_PRACH_MAX]; + prach_item_t *list[NUMBER_OF_NR_PRACH_MAX]; /// mutex for prach_list access pthread_mutex_t prach_list_mutex; } prach_list_t; diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index bc0c7b9461..27d7071511 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -51,7 +51,7 @@ void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rac rach_ind->slot = slot; rach_ind->number_of_pdus = 0; - prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, SEARCH_EXIST); + prach_item_t *prach_id = find_nr_prach(&gNB->prach_list, frame, slot, gNB->frame_parms.nb_antennas_rx, SEARCH_EXIST); if (!prach_id) { return; } diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 6f6d7c1102..9c14808382 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -563,7 +563,10 @@ int main(int argc, char **argv){ phy_init_nr_gNB(gNB); nr_phy_init_RU(ru); - nfapi_nr_prach_pdu_t *prach_pdu = &gNB->prach_list.list[0].pdu; + + prach_item_t *prach_data = calloc(1,sizeof(prach_item_t)); + gNB->prach_list.list[0] = prach_data; + nfapi_nr_prach_pdu_t *prach_pdu = &prach_data->pdu; prach_pdu->num_cs = get_NCS(NCS_config, format0, restrictedSetConfig); prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value = 1+(64/(N_ZC/prach_pdu->num_cs)); prach_pdu->prach_format = prach_format; @@ -765,26 +768,30 @@ int main(int argc, char **argv){ nfapi_nr_prach_config_t *cfg = &gNB->gNB_config.prach_config; nfapi_nr_num_prach_fd_occasions_t *occ = &cfg->num_prach_fd_occasions_list[prach_pdu->num_ra]; prach_pdu->num_prach_ocas=1; - prach_item_t in = {.frame = frame, - .slot = slot, - .pdu = *prach_pdu, - .rootSequenceIndex = occ->prach_root_sequence_index.value, - .numrootSequenceIndex = occ->num_root_sequences.value, - .msg1_frequencystart = occ->k1.value, - .mu = cfg->prach_sub_c_spacing.value, - .prach_sequence_length = cfg->prach_sequence_length.value, - .restricted_set = cfg->restricted_set_config.value, - .numerology_index = gNB->frame_parms.numerology_index, - .nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value, - .Xu = gNB->X_u, - .rx_prach = &gNB->rx_prach}; - rx_nr_prach_ru(&in, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); + prach_item_t *in = malloc(sizeof(prach_item_t) + + sizeof(c16_t) * gNB->gNB_config.carrier_config.num_rx_ant.value + * NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX * NR_PRACH_SEQ_LEN_L); + *in = (prach_item_t){.frame = frame, + .slot = slot, + .pdu = *prach_pdu, + .rootSequenceIndex = occ->prach_root_sequence_index.value, + .numrootSequenceIndex = occ->num_root_sequences.value, + .msg1_frequencystart = occ->k1.value, + .mu = cfg->prach_sub_c_spacing.value, + .prach_sequence_length = cfg->prach_sequence_length.value, + .restricted_set = cfg->restricted_set_config.value, + .numerology_index = gNB->frame_parms.numerology_index, + .nb_rx = gNB->gNB_config.carrier_config.num_rx_ant.value, + .Xu = gNB->X_u, + .rx_prach = &gNB->rx_prach, + .prach_buf = (void *)(in + 1)}; + rx_nr_prach_ru(in, ru->common.rxdata, ru->nr_frame_parms, ru->N_TA_offset); if (n_frames == 1) LOG_I(PHY, "ncs %d,num_seq %d\n", prach_pdu->num_cs, prach_config->num_prach_fd_occasions_list[fd_occasion].num_root_sequences.value); - rx_prach_out_t out = rx_nr_prach(&in, prachOccasion); + rx_prach_out_t out = rx_nr_prach(in, prachOccasion); // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", out.max_preamble_energy, out.max_preamble, // preamble_tx); @@ -807,13 +814,13 @@ int main(int argc, char **argv){ LOG_M("rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1); LOG_M("ru_rxsigF0.m","rxsF0", ru->common.rxdataF[0], frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot, 1, 1); - LOG_M("ru_prach_rxsigF0.m", "rxsF0", in.rxsigF[0][0], N_ZC, 1, 1); + LOG_M("ru_prach_rxsigF0.m", "rxsF0", in->prach_buf[0][0], N_ZC, 1, 1); LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1); LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1); #endif } + free(in); } - printf("SNR %f dB, UE Speed %f km/h: errors %u/%d (delay %f)\n", SNR, ue_speed, prach_errors, n_frames, delay_avg/(double)(n_frames-prach_errors)); if (input_fd) break; @@ -833,7 +840,7 @@ int main(int argc, char **argv){ nr_phy_free_RU(ru); free(RC.ru[0]); free(RC.ru); - + free(prach_data); phy_free_nr_gNB(gNB); // allocated in set_tdd_config_nr() int nb_slots_to_set = (1<prach_buf[0][aa]; + dst = (int16_t *)ru->prach_buf[aa][0]; src = (int16_t *)bufs->prachdstdecomp[aa % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx].pData; /* convert Network order to host order */ if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) { diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index d19d2c1f00..b89021931c 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -213,14 +213,14 @@ int trx_oran_ctlrecv(openair0_device_t *device, void *msg, ssize_t msg_len) void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) { - prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, SEARCH_EXIST); + prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, ru->nr_frame_parms->nb_antennas_rx, SEARCH_EXIST); ru_info_t ru_info = { .nb_rx = ru->nb_rx * ru->num_beams_period, .nb_tx = ru->nb_tx * ru->num_beams_period, .rxdataF = ru->common.rxdataF, .beam_id = ru->common.beam_id, .num_beams_period = ru->num_beams_period, - .prach_buf = prach_id ? prach_id->rxsigF : NULL, + .prach_buf = prach_id ? prach_id->prach_buf : NULL, }; RU_proc_t *proc = &ru->proc; diff --git a/radio/fhi_72/oran_isolate.h b/radio/fhi_72/oran_isolate.h index 6d7a47811b..21c63b0b48 100644 --- a/radio/fhi_72/oran_isolate.h +++ b/radio/fhi_72/oran_isolate.h @@ -31,6 +31,7 @@ #include "xran_fh_o_du.h" #include "openair1/PHY/impl_defs_nr.h" #include "openair1/PHY/TOOLS/tools_defs.h" +#include "openair1/PHY/defs_common.h" /* * Structure added to bear the information needed from OAI RU */ @@ -52,7 +53,7 @@ typedef struct ru_info_s { int num_beams_period; // Needed for Prach - c16_t (*prach_buf)[NB_ANTENNAS_RX][NR_PRACH_SEQ_LEN_L]; + c16_t (*prach_buf)[NUMBER_OF_NR_RU_PRACH_OCCASIONS_MAX][NR_PRACH_SEQ_LEN_L]; } ru_info_t; /** @brief Reads RX data (PRACH/PUSCH) of next slot. From 9a77e6edcf9d3117efe4b5ffb19ac9ec80421a84 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 16 Mar 2026 11:26:43 +0100 Subject: [PATCH 11/33] T: minor: remove target record_db from automatic building --- common/utils/T/tracer/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile index 5d0aed4029..246705be5d 100644 --- a/common/utils/T/tracer/Makefile +++ b/common/utils/T/tracer/Makefile @@ -8,7 +8,7 @@ CXXFLAGS=-Wall -g -pthread -DT_TRACER -I. -I../incgen -std=c++11 LIBS=-lm XLIBS=-lX11 -lpng -lXft -all: record record_db replay extract_config textlog enb ue vcd macpdu2wireshark \ +all: record replay extract_config textlog enb ue vcd macpdu2wireshark \ extract_input_subframe extract_output_subframe to_vcd extract multi \ gnb t_tracer_app_gnb t_tracer_app_ue gnb_mac csv From e0f95f2344cb72f04b51edfb1a8f88ec62839148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teodora=20Vladi=C4=87?= Date: Thu, 5 Mar 2026 10:54:54 +0100 Subject: [PATCH 12/33] [FHI72] Add verified Benetel FW versions Note: RAN550-1v1.4.1-M-25fa970 verified with both CUS and CUSM. At this stage, RAN550-1v2.0.5-M-92a9d2c verified with CUS only. --- doc/ORAN_FHI7.2_Tutorial.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index c90f9c72a5..95dc3b96d4 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -61,8 +61,8 @@ We tested the category A radio units listed below. |-----------------|---------------------------------------------| |VVDN LPRU |03-v3.0.5 | |LiteON RU |01.00.08/02.00.03/02.00.10 | -|Benetel 650 |RAN650-1v1.0.4-dda1bf5|RAN650-1v1.2.2-2fa04bc| -|Benetel 550 |RAN550-1v1.0.4-605a25a|RAN550-1v1.2.2-2fa04bc| +|Benetel 650 |RAN650-1v1.0.4-dda1bf5/RAN650-1v1.2.2-2fa04bc/RAN650-1v1.4.2-NM-c48047d| +|Benetel 550 |RAN550-1v1.0.4-605a25a/RAN550-1v1.2.2-2fa04bc/RAN550-1v1.4.1-M-25fa970/RAN550-1v2.0.5-M-92a9d2c| |Foxconn RPQN |v3.1.15q.551_rc10 | Tested libxran releases: From 63b048b2ff647d63df52a8bd92dee0502fc770b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teodora=20Vladi=C4=87?= Date: Wed, 4 Mar 2026 17:08:51 +0100 Subject: [PATCH 13/33] [FHI72] Refactor PRACH code Move PRACH slot checking from oaioran.c to oran_isolate.c because xran_is_prach_slot() compared the current slot instead of the scheduled. The current and the scheduled slot are the same in case of short format, but different in case of format 0. Therefore, with this commit, in xran_is_prach_slot() we check the `prach_id->slot` and not `slot`. --- radio/fhi_72/oaioran.c | 14 ++------------ radio/fhi_72/oran_isolate.c | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 617243b0fd..24adfe50b2 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -182,21 +182,11 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) int prach_end_sym = prach_info.N_dur + prach_start_sym; struct xran_ru_config *ru_conf = &fh_cfg->ru_conf; int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; - int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; - int tti = slots_per_frame * (frame) + (slot); - uint32_t subframe = slot / slots_per_subframe; - // PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4 - uint32_t is_prach_frame = (frame % prach_info.x == prach_info.y); - uint32_t is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (slot % slots_per_subframe)); int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; /* If it is PRACH slot, copy prach IQ from XRAN PRACH buffer to OAI PRACH buffer */ - if (is_prach_slot) { - if (!ru->prach_buf) { - LOG_W(HW, "we get rach data from ru, but it is not scheduled %d.%d\n", frame, slot); - return -1; - } + if (ru->prach_buf) { for (sym_idx = prach_start_sym; sym_idx < prach_end_sym; sym_idx++) { for (int aa = 0; aa < ru->nb_rx; aa++) { int16_t *dst, *src; @@ -249,7 +239,7 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) } // COMPMETHOD_BLKFLOAT } // aa } // symb_indx - } // is_prach_slot + } // ru->prach_buf return (0); } diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index d19d2c1f00..1881eae163 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -213,16 +213,31 @@ int trx_oran_ctlrecv(openair0_device_t *device, void *msg, ssize_t msg_len) void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) { - prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, SEARCH_EXIST); ru_info_t ru_info = { .nb_rx = ru->nb_rx * ru->num_beams_period, .nb_tx = ru->nb_tx * ru->num_beams_period, .rxdataF = ru->common.rxdataF, .beam_id = ru->common.beam_id, .num_beams_period = ru->num_beams_period, - .prach_buf = prach_id ? prach_id->rxsigF : NULL, + .prach_buf = NULL, }; + prach_item_t *prach_id = find_nr_prach(&ru->gNB_list[0]->prach_list, *frame, *slot, SEARCH_EXIST); + if (prach_id) { + struct xran_fh_config *fh_cfg = get_xran_fh_config(0); + int slots_per_subframe = 1 << fh_cfg->frame_conf.nNumerology; + uint32_t subframe = *slot / slots_per_subframe; // `slot` = slot in which PRACH is received + // PRACH occasion in a frame if and only if SFN % x == y, TS 38.211 Table 6.3.3.2-2/3/4 + nr_prach_info_t prach_info = get_prach_info(0); + bool is_prach_frame = (*frame % prach_info.x == prach_info.y); + bool is_prach_slot = is_prach_frame && xran_is_prach_slot(0, subframe, (prach_id->slot % slots_per_subframe)); // `prach_id->slot` = slot in which PRACH is scheduled + if (is_prach_slot) { + ru_info.prach_buf = prach_id->rxsigF; + } else { + LOG_W(HW, "[%d.%d] Expected PRACH reception of scheduled slot %d\n", *frame, *slot, prach_id->slot); + } + } + RU_proc_t *proc = &ru->proc; int f, sl; LOG_D(HW, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]); From 141690c780794819d5577c56cde5aa899dd1a17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teodora=20Vladi=C4=87?= Date: Wed, 4 Mar 2026 18:08:20 +0100 Subject: [PATCH 14/33] [FHI72] Handle long PRACH format Only static long PRACH configuration verified, i.e. PRACH C-plane is ignored by the RU. Note: Introducing `N_ZC` and `num_prbu` parameters is needed for testing with xran F release. However, in the K release, this information is stored in xran_rx_packet_ctl struct. --- doc/ORAN_FHI7.2_Tutorial.md | 9 + radio/fhi_72/oaioran.c | 27 +- ...73prb.fhi72.2x2-benetel550-long-prach.conf | 273 ++++++++++++++++++ 3 files changed, 300 insertions(+), 9 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-benetel550-long-prach.conf diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index 95dc3b96d4..80f3fa7d3c 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -563,6 +563,15 @@ flexran_prach_workaround=disabled dl_tuning_special_slot=0x13b6 ``` +In addition, PRACH format 0 is also verified with FW v2.0.5. An example gNB config file can be found at [`gnb.sa.band77.273prb.fhi72.2x2-benetel550-long-prach.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-benetel550-long-prach.conf). On the RU side, the following parameters shall be modified: +```bash +mimo_mode=1_3 +prach_format=long +prach_freq_offset_dynamic=false +lf_prach_compression_enable=true +lf_prach_slot_id=0 +``` + #### LITEON The OAI configuration file [`gnb.sa.band78.273prb.fhi72.4x4-liteon.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf) corresponds to: diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 24adfe50b2..283116d3da 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -178,6 +178,16 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) struct xran_fh_config *fh_cfg = get_xran_fh_config(0); nr_prach_info_t prach_info = get_prach_info(0); + uint16_t N_ZC, num_prbu; + if ((prach_info.format & 0xff) < 4) { + N_ZC = 839; + num_prbu = 70; + prach_info.N_dur = 1; + } else { + N_ZC = 139; + num_prbu = 12; + } + int prach_start_sym = prach_info.start_symbol; int prach_end_sym = prach_info.N_dur + prach_start_sym; struct xran_ru_config *ru_conf = &fh_cfg->ru_conf; @@ -198,25 +208,25 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) /* convert Network order to host order */ if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_NONE) { if (sym_idx == prach_start_sym) { - for (idx = 0; idx < 139 * 2; idx++) { + for (idx = 0; idx < N_ZC * 2; idx++) { dst[idx] = ((int16_t)ntohs(src[idx + g_kbar])); } } else { - for (idx = 0; idx < 139 * 2; idx++) { + for (idx = 0; idx < N_ZC * 2; idx++) { dst[idx] += ((int16_t)ntohs(src[idx + g_kbar])); } } } else if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_BLKFLOAT) { - int16_t local_dst[12 * 2 * N_SC_PER_PRB] __attribute__((aligned(64))); + int16_t local_dst[num_prbu * 2 * N_SC_PER_PRB] __attribute__((aligned(64))); #if defined(__i386__) || defined(__x86_64__) struct xranlib_decompress_request bfp_decom_req = {}; struct xranlib_decompress_response bfp_decom_rsp = {}; - int payload_len = (3 * ru_conf->iqWidth_PRACH + 1) * 12; // 12 = closest number of PRBs to 139 REs + int payload_len = (3 * ru_conf->iqWidth_PRACH + 1) * num_prbu; bfp_decom_req.data_in = (int8_t *)src; - bfp_decom_req.numRBs = 12; // closest number of PRBs to 139 REs + bfp_decom_req.numRBs = num_prbu; bfp_decom_req.len = payload_len; bfp_decom_req.compMethod = XRAN_COMPMETHOD_BLKFLOAT; bfp_decom_req.iqWidth = ru_conf->iqWidth_PRACH; @@ -225,16 +235,15 @@ static int read_prach_data(ru_info_t *ru, int frame, int slot) bfp_decom_rsp.len = 0; xranlib_decompress_avx512(&bfp_decom_req, &bfp_decom_rsp); #elif defined(__arm__) || defined(__aarch64__) - armral_bfp_decompression(ru_conf->iqWidth_PRACH, 12, (int8_t *)src, (int16_t *)local_dst); + armral_bfp_decompression(ru_conf->iqWidth_PRACH, num_prbu, (int8_t *)src, (int16_t *)local_dst); #else AssertFatal(1 == 0, "BFP decompression not supported on this architecture"); #endif - // note: this is hardwired for 139 point PRACH sequence, kbar=2 if (sym_idx == prach_start_sym) - for (idx = 0; idx < (139 * 2); idx++) + for (idx = 0; idx < (N_ZC * 2); idx++) dst[idx] = local_dst[idx + g_kbar]; else - for (idx = 0; idx < (139 * 2); idx++) + for (idx = 0; idx < (N_ZC * 2); idx++) dst[idx] += (local_dst[idx + g_kbar]); } // COMPMETHOD_BLKFLOAT } // aa diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-benetel550-long-prach.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-benetel550-long-prach.conf new file mode 100644 index 0000000000..ae356fb689 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-benetel550-long-prach.conf @@ -0,0 +1,273 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ( { sst = 1; }); }); + + nr_cellid = 1; + + ////////// Physical parameters: + + pdsch_AntennaPorts_XP = 2; + pdsch_AntennaPorts_N1 = 1; + maxMIMO_layers = 2; + pusch_AntennaPorts = 2; + do_CSIRS = 1; + do_SRS = 0; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + # n_TimingAdvanceOffset = 0; +# downlinkConfigCommon + #frequencyInfoDL + # center frequency = 3950.4 MHz + # selected SSB frequency = 3950.4 MHz + absoluteFrequencySSB = 663360; + dl_frequencyBand = 77; + # frequency point A = 3901.26 MHz + dl_absoluteFrequencyPointA = 660084; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 273; + #initialDownlinkBWP + #genericParameters + initialDLBWPlocationAndBandwidth = 1099; #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 = 77; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 273; + pMax = 23; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 1099; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 7; +#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; +#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; +#one (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 = 1; + 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_PositionsInBurst_Bitmap = 0x1; + +# 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 = -15; + } + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "172.21.6.5";}); + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.130"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.130"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 180; + pucch_TargetSNRx10 = 180; +# 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 = 10; + pusch_dtx_threshold = 10; + max_ldpc_iterations = 15; + tx_amp_backoff_dB = 12; # needs to match O-RU configuration + L1_rx_thread_core = 6; + L1_tx_thread_core = 7; + phase_compensation = 0; # needs to match O-RU configuration +} +); + +RUs = ( +{ + local_rf = "no"; + nb_tx = 2; + nb_rx = 2; + att_tx = 0; + att_rx = 0; + bands = [77]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + sf_extension = 0; + eNB_instances = [0]; + ru_thread_core = 8; + sl_ahead = 5; + tr_preference = "raw_if4p5"; # important: activate FHI7.2 + do_precoding = 0; # needs to match O-RU configuration +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level = "info"; + hw_log_level = "info"; + phy_log_level = "info"; + mac_log_level = "info"; + rlc_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + ngap_log_level = "info"; + f1ap_log_level = "info"; +}; + +fhi_72 = { + dpdk_devices = ("0000:6f:01.0"); + system_core = 9; + io_core = 10; + worker_cores = (11); + ru_addr = ("8c:1f:64:d1:11:1e"); + mtu = 9216; + fh_config = ({ + T1a_cp_dl = (419, 470); + T1a_cp_ul = (285, 336); + T1a_up = (294, 345); + Ta4 = (0, 831); + ru_config = { + iq_width = 9; + iq_width_prach = 9; + }; + prach_config = { + eAxC_offset = 8; + }; + }); +}; From 3c6644134cbc2d32fd948ff6899a5c01d0539d89 Mon Sep 17 00:00:00 2001 From: Teodora Date: Fri, 27 Feb 2026 16:16:18 +0100 Subject: [PATCH 15/33] Use VERSION_* binary test for checking the xran library E release An alternative would have been: if(xran_VERSION MATCHES "^5\.*") Co-authored-by: Robert Schmidt --- radio/fhi_72/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index 0fb5605662..eb1429542d 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -19,7 +19,7 @@ add_library(oran_fhlib_5g MODULE set(F_VERSION 6.1.8) find_package(xran REQUIRED) -if(xran_VERSION MATCHES "5.*") +if(xran_VERSION VERSION_GREATER_EQUAL 5 AND xran_VERSION VERSION_LESS 6) message(FATAL_ERROR "xran E release not supported starting from tag 2026.w08.\nPlease switch to F version ${F_VERSION}") elseif(xran_VERSION VERSION_EQUAL F_VERSION) target_compile_definitions(oran_fhlib_5g PRIVATE F_RELEASE) From 7a0311929d6a8c666aae1646d6fa016f5327fef1 Mon Sep 17 00:00:00 2001 From: Teodora Date: Thu, 26 Feb 2026 11:53:35 +0100 Subject: [PATCH 16/33] [FHI72] Set PRACH offset as optional parameter If the PRACH offset is set explicitely via config file, then its value will be used. Otherwise, eAxC_offset = max(Nrx,Ntx). Co-authored-by: Robert Schmidt --- radio/fhi_72/oran-config.c | 14 ++++---------- radio/fhi_72/oran-params.h | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index 0fac6452e6..fbd2858816 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -777,8 +777,7 @@ static bool set_fh_prach_config(void *mplane_api, const uint32_t max_num_ant, const paramdef_t *prachp, int nprach, - struct xran_prach_config *prach_config, - bool liteon_prach_eAxC_offset) + struct xran_prach_config *prach_config) { const split7_config_t *s7cfg = &oai0->split7; @@ -814,11 +813,8 @@ static bool set_fh_prach_config(void *mplane_api, xran_mplane_t *xran_mplane = (xran_mplane_t *)mplane_api; prach_config->eAxC_offset = xran_mplane->prach_offset; #else - uint8_t offset = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET)->u8ptr; - if (liteon_prach_eAxC_offset) - prach_config->eAxC_offset = offset; - else - prach_config->eAxC_offset = (offset != 0) ? offset : max_num_ant; + const paramdef_t *pd = gpd(prachp, nprach, ORAN_PRACH_CONFIG_EAXC_OFFSET); + prach_config->eAxC_offset = pd->paramflags & PARAMFLAG_PARAMSET ? *pd->u8ptr : max_num_ant; #endif g_kbar = *gpd(prachp, nprach, ORAN_PRACH_CONFIG_KBAR)->uptr; @@ -964,13 +960,11 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c fh_config->prachEnable = 1; // enable PRACH fh_config->srsEnable = 0; // enable SRS; used only if XRAN_CATEGORY_B // For LiteOn E release, no need to take care of prach eAxC_offset. xran lib is hacked to handle it. - bool liteon_prach_eAxC_offset = false; #if defined F_RELEASE fh_config->srsEnableCp = 0; // enable SRS CP; used only if XRAN_CATEGORY_B fh_config->SrsDelaySym = 0; // number of SRS delay symbols; used only if XRAN_CATEGORY_B fh_config->RunSlotPrbMapBySymbolEnable = *gpd(fhp, nfh, ORAN_CONFIG_RunSlotPrbMapBySymbol)->uptr; // enable RunSlotPrbMapBySymbol fh_config->LiteOnIgnoreUPSectionIdEnable = *gpd(fhp, nfh, ORAN_CONFIG_LiteOnIgnoreUPSectionId)->uptr; // enable LiteOnIgnoreUPSectionId - liteon_prach_eAxC_offset = fh_config->LiteOnIgnoreUPSectionIdEnable; #endif fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU @@ -982,7 +976,7 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c fh_config->GPS_Alpha = 0; // refers to alpha as defined in section 9.7.2 of ORAN spec. this value should be alpha*(1/1.2288ns), range 0 - 1e7 (ns); offset_nsec = (pConf->GPS_Beta - offset_sec * 100) * 1e7 + pConf->GPS_Alpha fh_config->GPS_Beta = 0; // beta value as defined in section 9.7.2 of ORAN spec. range -32767 ~ +32767; offset_sec = pConf->GPS_Beta / 100 - if (!set_fh_prach_config(mplane_api, oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf, liteon_prach_eAxC_offset)) + if (!set_fh_prach_config(mplane_api, oai0, fh_config->neAxc, prachp, nprach, &fh_config->prach_conf)) return false; /* SRS only used if XRAN_CATEGORY_B Note: srs_config->eAxC_offset >= prach_config->eAxC_offset + PRACH */ diff --git a/radio/fhi_72/oran-params.h b/radio/fhi_72/oran-params.h index caa56ccca4..bde414fde6 100644 --- a/radio/fhi_72/oran-params.h +++ b/radio/fhi_72/oran-params.h @@ -145,7 +145,7 @@ // clang-format off #define ORAN_PRACH_DESC {\ - {ORAN_PRACH_CONFIG_EAXC_OFFSET, "RU's eAxC offset for PRACH\n", PARAMFLAG_MANDATORY, .u8ptr=NULL, .defuintval=0, TYPE_UINT8, 0}, \ + {ORAN_PRACH_CONFIG_EAXC_OFFSET, "RU's eAxC offset for PRACH\n", 0, .u8ptr=NULL, .defuintval=0, TYPE_UINT8, 0}, \ {ORAN_PRACH_CONFIG_KBAR, "PRACH guard interval\n", 0, .uptr=NULL, .defuintval=4, TYPE_UINT, 0}, \ } // clang-format on From bbecfd5b0362174ea03b776e86d829e46fac5703 Mon Sep 17 00:00:00 2001 From: Teodora Date: Thu, 26 Feb 2026 15:22:36 +0100 Subject: [PATCH 17/33] [FHI72] Revert the xran modification introduced in the MR https://gitlab.eurecom.fr/oai/openairinterface5g/-/merge_requests/3668 1. Remove modifications done in the following xran functions: process_mbuf_batch(); xran_process_srs_sym(). => not even used with OAI 7.2 interface. 2. Also, remove xran_fs_get_num_dl_sym_sp() and xran_fs_get_num_ul_sym_sp() introduced in the same MR. 3. Remove LiteOnIgnoreUPSectionIdEnable parameter. Instead, use RunSlotPrbMapBySymbolEnable in a simple way for xran_process_rx_sym() function. Explanation: The xran expects UL UP packets with the same section IDs as indicated per UL CP message. However, the section IDs of received packets are 3 for mixed slot and 13 for UL slot. --- .../F/oaioran_F.patch | 371 +++--------------- radio/fhi_72/CMakeLists.txt | 2 +- radio/fhi_72/oran-config.c | 3 - radio/fhi_72/oran-params.h | 2 - 4 files changed, 50 insertions(+), 328 deletions(-) diff --git a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch index c30c6bd8fa..facf171672 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch @@ -1,5 +1,5 @@ diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h -index ac5f471..b1acb26 100644 +index ac5f471..fe27425 100644 --- a/fhi_lib/app/src/common.h +++ b/fhi_lib/app/src/common.h @@ -28,7 +28,7 @@ @@ -7,7 +7,7 @@ index ac5f471..b1acb26 100644 #include -#define VERSIONX "oran_f_release_v1.0" -+#define VERSIONX "oran_f_release_v1.8" ++#define VERSIONX "oran_f_release_v1.9" #define APP_O_DU 0 #define APP_O_RU 1 @@ -173,20 +173,18 @@ index eccc4ae..a97fdc6 100644 CPP_FLAGS_FULL := $(CPP_FLAGS) $(CPP_COMP) $(INC) $(DEF) CPP_FLAGS_FULL_SNC := $(CPP_FLAGS) $(CPP_COMP_SNC) $(INC) $(DEF) diff --git a/fhi_lib/lib/api/xran_fh_o_du.h b/fhi_lib/lib/api/xran_fh_o_du.h -index bacf597..18597d6 100644 +index bacf597..c37e132 100644 --- a/fhi_lib/lib/api/xran_fh_o_du.h +++ b/fhi_lib/lib/api/xran_fh_o_du.h -@@ -141,8 +141,8 @@ extern "C" { +@@ -141,7 +141,7 @@ extern "C" { #define XRAN_MAX_SECTIONS_PER_SYM (XRAN_MAX_SECTIONS_PER_SLOT) /**< Max number of different sections in single slot (section may be equal to RB allocation for UE) */ #define XRAN_MIN_SECTIONS_PER_SYM (XRAN_MIN_SECTIONS_PER_SLOT) /**< Min number of different sections in single slot (section may be equal to RB allocation for UE) */ -#define XRAN_MAX_FRAGMENT (4) /**< Max number of fragmentations in single symbol */ --#define XRAN_MAX_SET_BFWS (64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */ +#define XRAN_MAX_FRAGMENT (7) /**< Max number of fragmentations in single symbol */ -+#define XRAN_MAX_SET_BFWS (1) //(64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */ + #define XRAN_MAX_SET_BFWS (64) /**< Assumed 64Ant, BFP 9bit with 9K jumbo frame */ #define XRAN_MAX_PKT_BURST (448+4) /**< 4x14x8 symbols per ms */ - #define XRAN_N_MAX_BUFFER_SEGMENT XRAN_MAX_PKT_BURST /**< Max number of segments per ms */ @@ -419,6 +419,7 @@ struct xran_io_cfg { uint16_t num_rxq; /**< number of RX queues per VF */ char *dpdk_dev[XRAN_VF_MAX]; /**< VFs devices */ @@ -195,15 +193,7 @@ index bacf597..18597d6 100644 int32_t bbdev_mode; /**< DPDK for BBDev */ uint32_t dpdkIoVaMode; /**< IOVA Mode */ uint32_t dpdkMemorySize; /**< DPDK max memory allocation */ -@@ -713,6 +714,7 @@ struct xran_fh_config { - uint16_t max_sections_per_slot; /**< M-Plane settings for section */ - uint16_t max_sections_per_symbol; /**< M-Plane settings for section */ - int32_t RunSlotPrbMapBySymbolEnable; /**< enable prb mapping by symbol with multisection*/ -+ uint8_t LiteOnIgnoreUPSectionIdEnable; /**< handle LiteOn issue where section id on UP packet is wrongly set to 13. */ - - uint8_t dssEnable; /**< enable DSS (extension-9) */ - uint8_t dssPeriod; /**< DSS pattern period for LTE/NR */ -@@ -1193,6 +1195,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb, +@@ -1193,6 +1194,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb, */ int32_t xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond); @@ -594,7 +584,7 @@ index 08660f3..b5de607 100644 time_diff_nSymb = time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT); diff --git a/fhi_lib/lib/src/xran_common.c b/fhi_lib/lib/src/xran_common.c -index dc40ad9..1b88013 100644 +index dc40ad9..5968d01 100644 --- a/fhi_lib/lib/src/xran_common.c +++ b/fhi_lib/lib/src/xran_common.c @@ -31,7 +31,10 @@ @@ -608,110 +598,7 @@ index dc40ad9..1b88013 100644 #include #include #include -@@ -49,6 +52,8 @@ - #include "xran_printf.h" - #include "xran_mlog_lnx.h" - -+#include "xran_frame_struct.h" -+ - static struct timespec sleeptime = {.tv_nsec = 1E3 }; /* 1 us */ - - extern int32_t first_call; -@@ -529,13 +534,30 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru - if (pRbMap) - { - /** Get the prb_elem_id */ -+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ if(0 == p_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { -+ section_id_tmp = prb_elem_id_tmp = sect_id[i]; -+ } else { -+ u_int8_t mixed_ul_sym_start = 0; -+ if (xran_fs_get_slot_type(xran_port, CC_ID[i], tti, XRAN_SLOT_TYPE_SP)) { -+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID[i], tti); -+ } -+ u_int8_t section_id_tmp = symb_id[i] - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ //Note for future reference when using MTU 1500 -+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ } -+ - total_sections=0; - if(pRbMap->prbMap[0].bf_weight.extType == 1) - { - for(idxElm=0 ; idxElm < pRbMap->nPrbElm ; idxElm++) - { - total_sections += pRbMap->prbMap[idxElm].bf_weight.numSetBFWs; -- if(total_sections >= (sect_id[i] + 1)) -+ if(total_sections >= (/*sect_id[i]*/ prb_elem_id_tmp + 1)) - { - prb_elem_id[i] = idxElm; - break; -@@ -544,12 +566,12 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru - } - else - { -- prb_elem_id[i] = sect_id[i]; -+ prb_elem_id[i] = prb_elem_id_tmp; /*sect_id[i];*/ - } - - if (prb_elem_id[i] >= pRbMap->nPrbElm) - { -- print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", sect_id[i], prb_elem_id[i], pRbMap->nPrbElm); -+ print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", /*sect_id[i]*/ section_id_tmp, prb_elem_id[i], pRbMap->nPrbElm); - ret_data[i] = MBUF_FREE; - continue; - } -@@ -615,13 +637,30 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru - if (pRbMap) - { - /** Get the prb_elem_id */ -+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ if(0 == p_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { -+ section_id_tmp = prb_elem_id_tmp = sect_id[i]; -+ } else { -+ u_int8_t mixed_ul_sym_start = 0; -+ if (xran_fs_get_slot_type(xran_port, CC_ID[i], tti, XRAN_SLOT_TYPE_SP)) { -+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID[i], tti); -+ } -+ u_int8_t section_id_tmp = symb_id[i] - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ //Note for future reference when using MTU 1500 -+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ } -+ - total_sections=0; - if(pRbMap->prbMap[0].bf_weight.extType == 1) - { - for(idxElm=0 ; idxElm < pRbMap->nPrbElm ; idxElm++) - { - total_sections += pRbMap->prbMap[idxElm].bf_weight.numSetBFWs; -- if(total_sections >= (sect_id[i] + 1)) -+ if(total_sections >= (/*sect_id[i]*/ prb_elem_id_tmp + 1)) - { - prb_elem_id[i] = idxElm; - break; -@@ -630,12 +669,12 @@ int process_mbuf_batch(struct rte_mbuf* pkt_q[], void* handle, int16_t num, stru - } - else - { -- prb_elem_id[i] = sect_id[i]; -+ prb_elem_id[i] = prb_elem_id_tmp; /*sect_id[i];*/ - } - - if (prb_elem_id[i] >= pRbMap->nPrbElm) - { -- print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", sect_id[i], prb_elem_id[i], pRbMap->nPrbElm); -+ print_err("sect_id %d, prb_elem_id %d !=pRbMap->nPrbElm %d\n", /*sect_id[i]*/ section_id_tmp, prb_elem_id[i], pRbMap->nPrbElm); - ret_data[i] = MBUF_FREE; - continue; - } -@@ -714,11 +753,14 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) +@@ -714,11 +717,14 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) uint8_t compMeth = 0; uint8_t iqWidth = 0; @@ -726,7 +613,7 @@ index dc40ad9..1b88013 100644 if(first_call == 0) return ret; -@@ -733,9 +775,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) +@@ -733,9 +739,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) return MBUF_FREE; num_bytes = xran_extract_iq_samples(pkt, &iq_samp_buf, @@ -738,7 +625,7 @@ index dc40ad9..1b88013 100644 if (num_bytes <= 0) { print_err("num_bytes is wrong [%d]\n", num_bytes); -@@ -781,10 +823,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) +@@ -781,10 +787,9 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) else { @@ -752,7 +639,7 @@ index dc40ad9..1b88013 100644 #ifndef FCN_ADAPT if(valid_res != 0) { -@@ -807,8 +848,7 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) +@@ -807,8 +812,7 @@ process_mbuf(struct rte_mbuf *pkt, void* handle, struct xran_eaxc_info *p_cid) PrachCfg = &(p_dev_ctx->PrachCPConfig); } @@ -762,7 +649,7 @@ index dc40ad9..1b88013 100644 /* PRACH packet has ruportid = num_eAxc + ant_id */ Ant_ID -= PrachCfg->eAxC_offset; symbol_total_bytes[p_dev_ctx->xran_port_id][CC_ID][Ant_ID] += num_bytes; -@@ -1412,7 +1452,7 @@ int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struc +@@ -1412,7 +1416,7 @@ int generate_cpmsg_prach(void *pHandle, struct xran_cp_gen_params *params, struc if(XRAN_FILTERINDEX_PRACH_ABC == pPrachCPConfig->filterIdx) { timeOffset = timeOffset >> nNumerology; //original number is Tc, convert to Ts based on mu @@ -771,7 +658,7 @@ index dc40ad9..1b88013 100644 timeOffset += 16; } else -@@ -1547,8 +1587,7 @@ int32_t ring_processing_func(void* args) +@@ -1547,8 +1551,7 @@ int32_t ring_processing_func(void* args) for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i++){ for(qi = 0; qi < ctx->rxq_per_port[i]; qi++) { @@ -1081,18 +968,10 @@ index 4acade1..c939edc 100644 for(i = 0; i < xran_ports_num; i++){ g_xran_dev_ctx[i] = pCtx; diff --git a/fhi_lib/lib/src/xran_dev.h b/fhi_lib/lib/src/xran_dev.h -index 0371a53..778b38d 100644 +index 0371a53..b417619 100644 --- a/fhi_lib/lib/src/xran_dev.h +++ b/fhi_lib/lib/src/xran_dev.h -@@ -201,6 +201,7 @@ struct __rte_cache_aligned xran_device_ctx - - int32_t DynamicSectionEna; - int32_t RunSlotPrbMapBySymbolEnable; -+ uint8_t LiteOnIgnoreUPSectionIdEnable; /**< handle LiteOn issue where section id on UP packet is wrongly set to 13. */ - int64_t offset_sec; - int64_t offset_nsec; //offset to GPS time calcuated based on alpha and beta - uint32_t interval_us_local; -@@ -254,6 +255,11 @@ struct __rte_cache_aligned xran_device_ctx +@@ -254,6 +254,11 @@ struct __rte_cache_aligned xran_device_ctx int32_t sym_up; /**< when we start sym 0 of up with respect to OTA time as measured in symbols */ int32_t sym_up_ul; @@ -1105,45 +984,17 @@ index 0371a53..778b38d 100644 void *TtiCbParam[XRAN_CB_MAX]; uint32_t SkipTti[XRAN_CB_MAX]; diff --git a/fhi_lib/lib/src/xran_frame_struct.c b/fhi_lib/lib/src/xran_frame_struct.c -index fbb1298..44aaf92 100644 +index fbb1298..385de76 100644 --- a/fhi_lib/lib/src/xran_frame_struct.c +++ b/fhi_lib/lib/src/xran_frame_struct.c -@@ -519,4 +519,20 @@ int32_t xran_fs_get_symbol_type(uint32_t PortId, int32_t nCellIdx, int32_t nSlot +@@ -518,5 +518,3 @@ int32_t xran_fs_get_symbol_type(uint32_t PortId, int32_t nCellIdx, int32_t nSlot + return xran_fs_slot_symb_type[PortId][nCellIdx][nSfIdxMod][nSymbIdx]; } - -+uint32_t xran_fs_get_num_dl_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx) -+{ -+ int32_t nSfIdxMod; -+ -+ nSfIdxMod = xran_fs_slot_limit(PortId, nSlotdx) % ((xran_fs_num_slot_tdd_loop[PortId][nCellIdx] > 0) ? xran_fs_num_slot_tdd_loop[PortId][nCellIdx]: 1); -+ -+ return xran_fs_num_dl_sym_sp[PortId][nCellIdx][nSfIdxMod]; -+} - -+uint32_t xran_fs_get_num_ul_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx) -+{ -+ int32_t nSfIdxMod; -+ -+ nSfIdxMod = xran_fs_slot_limit(PortId, nSlotdx) % ((xran_fs_num_slot_tdd_loop[PortId][nCellIdx] > 0) ? xran_fs_num_slot_tdd_loop[PortId][nCellIdx]: 1); -+ -+ return xran_fs_num_ul_sym_sp[PortId][nCellIdx][nSfIdxMod]; -+} -diff --git a/fhi_lib/lib/src/xran_frame_struct.h b/fhi_lib/lib/src/xran_frame_struct.h -index 7ed0a3a..8e66945 100644 ---- a/fhi_lib/lib/src/xran_frame_struct.h -+++ b/fhi_lib/lib/src/xran_frame_struct.h -@@ -75,6 +75,8 @@ uint32_t xran_fs_slot_limit_init(uint32_t PortId, int32_t tti_interval_us); - uint32_t xran_fs_get_max_slot(uint32_t PortId); - uint32_t xran_fs_get_max_slot_SFN(uint32_t PortId); - int32_t xran_fs_get_symbol_type(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx, int32_t nSymbIdx); -+uint32_t xran_fs_get_num_dl_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx); -+uint32_t xran_fs_get_num_ul_sym_sp(uint32_t PortId, int32_t nCellIdx, int32_t nSlotdx); - - #ifdef __cplusplus - } +- +- diff --git a/fhi_lib/lib/src/xran_main.c b/fhi_lib/lib/src/xran_main.c -index 7c472d7..db03d94 100644 +index 7c472d7..758616d 100644 --- a/fhi_lib/lib/src/xran_main.c +++ b/fhi_lib/lib/src/xran_main.c @@ -35,7 +35,11 @@ @@ -1847,15 +1698,7 @@ index 7c472d7..db03d94 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3754,6 +3808,7 @@ xran_open(void *pHandle, struct xran_fh_config* pConf) - p_xran_dev_ctx->puschMaskSlot = pConf->puschMaskSlot; - p_xran_dev_ctx->DynamicSectionEna = pConf->DynamicSectionEna; - p_xran_dev_ctx->RunSlotPrbMapBySymbolEnable = pConf->RunSlotPrbMapBySymbolEnable; -+ p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable = pConf->LiteOnIgnoreUPSectionIdEnable; - p_xran_dev_ctx->dssEnable = pConf->dssEnable; - p_xran_dev_ctx->dssPeriod = pConf->dssPeriod; - for(i=0; idssPeriod; i++) { -@@ -4034,6 +4089,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, +@@ -4034,6 +4088,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, return tti; } @@ -1880,7 +1723,7 @@ index 7c472d7..db03d94 100644 int32_t xran_set_debug_stop(int32_t value, int32_t count) { -@@ -4208,7 +4281,7 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str +@@ -4208,7 +4280,7 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str int32_t i = 0, j = 0, nPrbElm = 0; int16_t iqwidth = p_PrbMapIn->prbMap[0].iqWidth; struct xran_prb_elm *p_prb_elm_src, *p_prb_elm_dst; @@ -1889,7 +1732,7 @@ index 7c472d7..db03d94 100644 int32_t nRBStart_tmp, nRBremain, nStartSymb, nEndSymb, nRBStart, nRBEnd, nRBSize; // int32_t eth_xran_up_headers_sz = sizeof(struct eth_xran_up_pkt_hdr); // int32_t nmaxRB = (mtu - eth_xran_up_headers_sz - RTE_PKTMBUF_HEADROOM)/XRAN_PAYLOAD_1_RB_SZ(iqwidth); -@@ -4217,7 +4290,6 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str +@@ -4217,7 +4289,6 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str if (mtu==9600) nmaxRB--; //for some reason when mtu is 9600, only 195 RB can be sent, not 196 @@ -1897,7 +1740,7 @@ index 7c472d7..db03d94 100644 memcpy(p_PrbMapOut, p_PrbMapIn, sizeof(struct xran_prb_map)); for(i = 0; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++) { -@@ -4292,26 +4364,30 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str +@@ -4292,27 +4363,23 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str for(; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++) { @@ -1906,8 +1749,7 @@ index 7c472d7..db03d94 100644 - prbMapTemp[nPrbElm].numSymb++; - } - else -+ if((prbMapTemp[i].nRBSize != 0)) - { +- { - nPrbElm++; - prbMapTemp[nPrbElm].nStartSymb = prbMapTemp[i].nStartSymb; - prbMapTemp[nPrbElm].nRBStart = prbMapTemp[i].nRBStart; @@ -1922,31 +1764,27 @@ index 7c472d7..db03d94 100644 - - nRBStart = prbMapTemp[i].nRBStart; - nRBSize = prbMapTemp[i].nRBSize; -+ if (false) // Force it to generate multiple prbMapElm, one for each symbol even if they are of the same RBs -+ //if((nRBStart == prbMapTemp[i].nRBStart) && (nRBSize == prbMapTemp[i].nRBSize)) -+ { -+ prbMapTemp[nPrbElm].numSymb++; -+ } -+ else -+ { -+ nPrbElm++; -+ prbMapTemp[nPrbElm].nStartSymb = prbMapTemp[i].nStartSymb; -+ prbMapTemp[nPrbElm].nRBStart = prbMapTemp[i].nRBStart; -+ prbMapTemp[nPrbElm].nRBSize = prbMapTemp[i].nRBSize; -+ prbMapTemp[nPrbElm].nBeamIndex = prbMapTemp[i].nBeamIndex; -+ prbMapTemp[nPrbElm].bf_weight_update = prbMapTemp[i].bf_weight_update; -+ prbMapTemp[nPrbElm].compMethod = prbMapTemp[i].compMethod; -+ prbMapTemp[nPrbElm].iqWidth = prbMapTemp[i].iqWidth; -+ prbMapTemp[nPrbElm].ScaleFactor = prbMapTemp[i].ScaleFactor; -+ prbMapTemp[nPrbElm].reMask = prbMapTemp[i].reMask; -+ prbMapTemp[nPrbElm].BeamFormingType = prbMapTemp[i].BeamFormingType; +- } ++ /* force using a separate section for each symbol in one multisection CP (both DL and UL) message; ++ * when generating DL UP, symbol index should be within nStartSymb and (nStartSymb + numSymb); ++ * nPrbElm doesn't have any affect on UL UP */ ++ nPrbElm++; ++ prbMapTemp[nPrbElm].nStartSymb = prbMapTemp[i].nStartSymb; ++ prbMapTemp[nPrbElm].nRBStart = prbMapTemp[i].nRBStart; ++ prbMapTemp[nPrbElm].nRBSize = prbMapTemp[i].nRBSize; ++ prbMapTemp[nPrbElm].nBeamIndex = prbMapTemp[i].nBeamIndex; ++ prbMapTemp[nPrbElm].bf_weight_update = prbMapTemp[i].bf_weight_update; ++ prbMapTemp[nPrbElm].compMethod = prbMapTemp[i].compMethod; ++ prbMapTemp[nPrbElm].iqWidth = prbMapTemp[i].iqWidth; ++ prbMapTemp[nPrbElm].ScaleFactor = prbMapTemp[i].ScaleFactor; ++ prbMapTemp[nPrbElm].reMask = prbMapTemp[i].reMask; ++ prbMapTemp[nPrbElm].BeamFormingType = prbMapTemp[i].BeamFormingType; + -+ nRBStart = prbMapTemp[i].nRBStart; -+ nRBSize = prbMapTemp[i].nRBSize; -+ } - } ++ nRBStart = prbMapTemp[i].nRBStart; ++ nRBSize = prbMapTemp[i].nRBSize; } + for(i = 0; i < nPrbElm; i++) diff --git a/fhi_lib/lib/src/xran_mem_mgr.c b/fhi_lib/lib/src/xran_mem_mgr.c index e1dcb6c..b3c3fae 100644 --- a/fhi_lib/lib/src/xran_mem_mgr.c @@ -1980,7 +1818,7 @@ index 7d4a5d0..b9b44ac 100644 #endif } diff --git a/fhi_lib/lib/src/xran_rx_proc.c b/fhi_lib/lib/src/xran_rx_proc.c -index e7056f4..34b6d3b 100644 +index e7056f4..4941360 100644 --- a/fhi_lib/lib/src/xran_rx_proc.c +++ b/fhi_lib/lib/src/xran_rx_proc.c @@ -35,7 +35,11 @@ @@ -1995,127 +1833,16 @@ index e7056f4..34b6d3b 100644 #include #include -@@ -339,13 +343,33 @@ int32_t xran_process_srs_sym(void *arg, - pRbMap = (struct xran_prb_map *) p_xran_dev_ctx->sFHSrsRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers->pData; - if(pRbMap) - { -- prbMapElm = &pRbMap->prbMap[sect_id]; -- if(sect_id >= pRbMap->nPrbElm) -+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ if(0 == p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { -+ section_id_tmp = prb_elem_id_tmp = sect_id; -+ } else { -+ /** Get the prb_elem_id */ -+ int8_t xran_port = xran_dev_ctx_get_port_id(p_xran_dev_ctx); -+ u_int8_t mixed_ul_sym_start = 0; -+ if (xran_fs_get_slot_type(xran_port, CC_ID, tti, XRAN_SLOT_TYPE_SP)) { -+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID, tti); -+ } -+ -+ section_id_tmp = symb_id - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ //Note for future reference when using MTU 1500 -+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ } -+ -+ prbMapElm = &pRbMap->prbMap[prb_elem_id_tmp /*sect_id*/]; -+ if(/*sect_id*/ prb_elem_id_tmp >= pRbMap->nPrbElm) - { -- print_err("sect_id %d !=pRbMap->nPrbElm %d\n", sect_id,pRbMap->nPrbElm); -- *mb_free = MBUF_FREE; -- return size; -- } -+ print_err("sect_id %d !=pRbMap->nPrbElm %d\n", sect_id,pRbMap->nPrbElm); -+ *mb_free = MBUF_FREE; -+ return size; -+ } - } - else - { -@@ -397,7 +421,25 @@ int32_t xran_process_srs_sym(void *arg, - else */ - { - struct xran_section_desc *p_sec_desc = NULL; -- prbMapElm = &pRbMap->prbMap[sect_id]; -+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ if(0 == p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { -+ section_id_tmp = prb_elem_id_tmp = sect_id; -+ } else { -+ int8_t xran_port = xran_dev_ctx_get_port_id(p_xran_dev_ctx); -+ u_int8_t mixed_ul_sym_start = 0; -+ if (xran_fs_get_slot_type(xran_port, CC_ID, tti, XRAN_SLOT_TYPE_SP)) { -+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID, tti); -+ } -+ u_int8_t section_id_tmp = symb_id - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ //Note for future reference when using MTU 1500 -+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ } -+ -+ prbMapElm = &pRbMap->prbMap[prb_elem_id_tmp /*sect_id*/]; - // sec_desc_idx = 0;//prbMapElm->nSecDesc[symb_id]; - sec_desc_idx = prbMapElm->nSecDesc[symb_id]; - -@@ -537,14 +579,33 @@ int32_t xran_process_rx_sym(void *arg, +@@ -537,6 +541,9 @@ int32_t xran_process_rx_sym(void *arg, pos = (char*) p_xran_dev_ctx->sFrontHaulRxBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers[symb_id].pData; pRbMap = (struct xran_prb_map *) p_xran_dev_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][CC_ID][Ant_ID].sBufferList.pBuffers->pData; if(pRbMap){ -- /** Get the prb_elem_id */ -+ u_int8_t section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ u_int8_t prb_elem_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13 -+ if(0 == p_xran_dev_ctx->LiteOnIgnoreUPSectionIdEnable) { -+ section_id_tmp = prb_elem_id_tmp = sect_id; -+ } else { -+ /** Get the prb_elem_id */ -+ int8_t xran_port = xran_dev_ctx_get_port_id(p_xran_dev_ctx); -+ u_int8_t mixed_ul_sym_start = 0; -+ if (xran_fs_get_slot_type(xran_port, CC_ID, tti, XRAN_SLOT_TYPE_SP)) { -+ mixed_ul_sym_start = XRAN_NUM_OF_SYMBOL_PER_SLOT - xran_fs_get_num_ul_sym_sp(xran_port, CC_ID, tti); -+ } -+ -+ section_id_tmp = symb_id - mixed_ul_sym_start; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ prb_elem_id_tmp = section_id_tmp; // hack for LiteON FR2 : receive UP section ID = 13, MTU 9000 -+ //Note for future reference when using MTU 1500 -+ //prb_elem_id_tmp = 2*section_id_tmp; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ //if (start_prbu !=0) // For LiteON FR2 : receive UP section ID = 13, MTU 1500 -+ // prb_elem_id_tmp++; // For LiteON FR2 : receive UP section ID = 13, MTU 1500 ++ if (p_xran_dev_ctx->RunSlotPrbMapBySymbolEnable) { ++ sect_id = (pRbMap->nPrbElm == XRAN_NUM_OF_SYMBOL_PER_SLOT) ? symb_id : symb_id - (XRAN_NUM_OF_SYMBOL_PER_SLOT - pRbMap->nPrbElm); + } -+ + /** Get the prb_elem_id */ total_sections=0; if(pRbMap->prbMap[0].bf_weight.extType == 1) - { - for(i=0 ; i < pRbMap->nPrbElm ; i++) - { - total_sections += pRbMap->prbMap[i].bf_weight.numSetBFWs; -- if(total_sections >= (sect_id + 1)) -+ if(total_sections >= (/*sect_id*/ section_id_tmp + 1)) - { - prb_elem_id = i; - break; -@@ -553,7 +614,7 @@ int32_t xran_process_rx_sym(void *arg, - } - else - { -- prb_elem_id = sect_id; -+ prb_elem_id = prb_elem_id_tmp; /*sect_id*/; - } - - prbMapElm = &pRbMap->prbMap[prb_elem_id]; -@@ -597,7 +658,7 @@ int32_t xran_process_rx_sym(void *arg, - if(p_sec_desc){ - mb = p_sec_desc->pCtrl; - if(mb){ -- rte_pktmbuf_free(mb); -+ rte_pktmbuf_free(mb); - } - p_sec_desc->pData = iq_data_start; - p_sec_desc->pCtrl = mbuf; diff --git a/fhi_lib/lib/src/xran_timer.c b/fhi_lib/lib/src/xran_timer.c index 14a6a41..55182d8 100644 --- a/fhi_lib/lib/src/xran_timer.c diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index eb1429542d..471cd4fd19 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -16,7 +16,7 @@ add_library(oran_fhlib_5g MODULE oran-init.c ) -set(F_VERSION 6.1.8) +set(F_VERSION 6.1.9) find_package(xran REQUIRED) if(xran_VERSION VERSION_GREATER_EQUAL 5 AND xran_VERSION VERSION_LESS 6) diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index fbd2858816..b6833330f1 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -432,12 +432,10 @@ void print_fh_config(const struct xran_fh_config *fh_config) #if defined F_RELEASE printf("\ RunSlotPrbMapBySymbolEnable %d\n\ - LiteOnIgnoreUPSectionIdEnable %d\n\ dssEnable %d\n\ dssPeriod %d\n\ technology[XRAN_MAX_DSS_PERIODICITY] (not filled as DSS disabled)\n", fh_config->RunSlotPrbMapBySymbolEnable, - fh_config->LiteOnIgnoreUPSectionIdEnable, fh_config->dssEnable, fh_config->dssPeriod); #endif @@ -964,7 +962,6 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c fh_config->srsEnableCp = 0; // enable SRS CP; used only if XRAN_CATEGORY_B fh_config->SrsDelaySym = 0; // number of SRS delay symbols; used only if XRAN_CATEGORY_B fh_config->RunSlotPrbMapBySymbolEnable = *gpd(fhp, nfh, ORAN_CONFIG_RunSlotPrbMapBySymbol)->uptr; // enable RunSlotPrbMapBySymbol - fh_config->LiteOnIgnoreUPSectionIdEnable = *gpd(fhp, nfh, ORAN_CONFIG_LiteOnIgnoreUPSectionId)->uptr; // enable LiteOnIgnoreUPSectionId #endif fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU diff --git a/radio/fhi_72/oran-params.h b/radio/fhi_72/oran-params.h index bde414fde6..d19047381c 100644 --- a/radio/fhi_72/oran-params.h +++ b/radio/fhi_72/oran-params.h @@ -107,7 +107,6 @@ #define CONFIG_STRING_ORAN_FH "fh_config" #define ORAN_CONFIG_RunSlotPrbMapBySymbol "RunSlotPrbMapBySymbol" -#define ORAN_CONFIG_LiteOnIgnoreUPSectionId "LiteOnIgnoreUPSectionId" #define ORAN_FH_CONFIG_T1A_CP_DL "T1a_cp_dl" #define ORAN_FH_CONFIG_T1A_CP_UL "T1a_cp_ul" #define ORAN_FH_CONFIG_T1A_UP "T1a_up" @@ -118,7 +117,6 @@ // clang-format off #define ORAN_FH_DESC { \ {ORAN_CONFIG_RunSlotPrbMapBySymbol, "RunSlotPrbMapBySymbol\n", PARAMFLAG_BOOL, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ - {ORAN_CONFIG_LiteOnIgnoreUPSectionId, "Liteon Ignore Section Id\n", PARAMFLAG_BOOL, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ {ORAN_FH_CONFIG_T1A_CP_DL, "T1a_cp_dl" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_CP_UL, "T1a_cp_ul" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_UP, "T1a_up" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ From c2ccca022807e4eebd23655cbfbecb1284ac27de Mon Sep 17 00:00:00 2001 From: Teodora Date: Thu, 26 Feb 2026 16:17:24 +0100 Subject: [PATCH 18/33] [FHI72] Simplify RunSlotPrbMapBySymbol and add in the README --- doc/ORAN_FHI7.2_Tutorial.md | 1 + radio/fhi_72/oran-config.c | 3 ++- radio/fhi_72/oran-init.c | 12 ++---------- radio/fhi_72/oran-params.h | 4 ++-- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index c90f9c72a5..60744ccaa0 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -1012,6 +1012,7 @@ Edit the sample OAI gNB configuration file and check following parameters: [Memory in DPDK](https://www.dpdk.org/memory-in-dpdk-part-2-deep-dive-into-iova/) * `owdm_enable`: used for eCPRI One-Way Delay Measurements; it depends if the RU supports it; if not set to 1 (enabled), default value is 0 (disabled) * `fh_config` + * `RunSlotPrbMapBySymbol`: enable CP multisection (one symbol per section); default value is 0 * DU delay profile (`T1a` and `Ta4`): pairs of numbers `(x, y)` specifying minimum and maximum delays * `ru_config`: RU-specific configuration: * `iq_width`: Width of DL/UL IQ samples: if 16, no compression, if <16, applies diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c index b6833330f1..4478154e6c 100644 --- a/radio/fhi_72/oran-config.c +++ b/radio/fhi_72/oran-config.c @@ -961,7 +961,6 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c #if defined F_RELEASE fh_config->srsEnableCp = 0; // enable SRS CP; used only if XRAN_CATEGORY_B fh_config->SrsDelaySym = 0; // number of SRS delay symbols; used only if XRAN_CATEGORY_B - fh_config->RunSlotPrbMapBySymbolEnable = *gpd(fhp, nfh, ORAN_CONFIG_RunSlotPrbMapBySymbol)->uptr; // enable RunSlotPrbMapBySymbol #endif fh_config->puschMaskEnable = 0; // enable PUSCH mask; only used if id = O_RU fh_config->puschMaskSlot = 0; // specific which slot PUSCH channel masked; only used if id = O_RU @@ -1005,6 +1004,8 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c fh_config->max_sections_per_symbol = 0; // not used in xran #if defined F_RELEASE + fh_config->RunSlotPrbMapBySymbolEnable = *gpd(fhp, nfh, ORAN_CONFIG_CP_MULTISECTION)->uptr; // enable PRB mapping by symbol with multisection + fh_config->dssEnable = 0; // enable DSS (extension-9) fh_config->dssPeriod = 0; // DSS pattern period for LTE/NR // fh_config->technology[XRAN_MAX_DSS_PERIODICITY] // technology array represents slot is LTE(0)/NR(1); used only if DSS enabled diff --git a/radio/fhi_72/oran-init.c b/radio/fhi_72/oran-init.c index 00c0e30746..6680c56bce 100644 --- a/radio/fhi_72/oran-init.c +++ b/radio/fhi_72/oran-init.c @@ -315,16 +315,8 @@ static void oran_allocate_buffers(void *handle, }; #if defined F_RELEASE - uint32_t size_of_prb_map; - if (fh_config->RunSlotPrbMapBySymbolEnable) { - // For Liteon FR2 with RunSlotPrbMapBySymbolEnable, xran_prb_map will have xran_prb_elm prbMap[14] - size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (XRAN_NUM_OF_SYMBOL_PER_SLOT); - } - else { - // For non-Liteon w/o RunSlotPrbMapBySymbolEnable, xran_prb_map will have xran_prb_elm prbMap[1] - uint32_t numPrbElm = xran_get_num_prb_elm(&dlPm, mtu); - size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm); - } + uint32_t numPrbElm = (fh_config->RunSlotPrbMapBySymbolEnable) ? XRAN_NUM_OF_SYMBOL_PER_SLOT : xran_get_num_prb_elm(&dlPm, mtu); + uint32_t size_of_prb_map = sizeof(struct xran_prb_map) + sizeof(struct xran_prb_elm) * (numPrbElm); #endif // PDSCH diff --git a/radio/fhi_72/oran-params.h b/radio/fhi_72/oran-params.h index d19047381c..3644f0e5f2 100644 --- a/radio/fhi_72/oran-params.h +++ b/radio/fhi_72/oran-params.h @@ -106,7 +106,7 @@ #define CONFIG_STRING_ORAN_FH "fh_config" -#define ORAN_CONFIG_RunSlotPrbMapBySymbol "RunSlotPrbMapBySymbol" +#define ORAN_CONFIG_CP_MULTISECTION "RunSlotPrbMapBySymbol" #define ORAN_FH_CONFIG_T1A_CP_DL "T1a_cp_dl" #define ORAN_FH_CONFIG_T1A_CP_UL "T1a_cp_ul" #define ORAN_FH_CONFIG_T1A_UP "T1a_up" @@ -116,7 +116,7 @@ // clang-format off #define ORAN_FH_DESC { \ - {ORAN_CONFIG_RunSlotPrbMapBySymbol, "RunSlotPrbMapBySymbol\n", PARAMFLAG_BOOL, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ + {ORAN_CONFIG_CP_MULTISECTION, "RunSlotPrbMapBySymbol\n", PARAMFLAG_BOOL, .iptr=NULL, .defintval=0, TYPE_INT32, 0}, \ {ORAN_FH_CONFIG_T1A_CP_DL, "T1a_cp_dl" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_CP_UL, "T1a_cp_ul" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ {ORAN_FH_CONFIG_T1A_UP, "T1a_up" ORAN_FH_HLP_CPLT, PARAMFLAG_MANDATORY, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ From a7ff360c73943c260e9d46776fb95bacedc23b88 Mon Sep 17 00:00:00 2001 From: Teodora Date: Mon, 2 Mar 2026 11:35:12 +0100 Subject: [PATCH 19/33] [FHI72] Add Liteon FR2 support in the FHI tutorial and a reference config file --- doc/ORAN_FHI7.2_Tutorial.md | 31 +- ...gnb.sa.band257.66prb.fhi72.2x2-liteon.conf | 281 ++++++++++++++++++ 2 files changed, 305 insertions(+), 7 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.66prb.fhi72.2x2-liteon.conf diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index 60744ccaa0..274866b8dd 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -565,12 +565,6 @@ dl_tuning_special_slot=0x13b6 #### LITEON -The OAI configuration file [`gnb.sa.band78.273prb.fhi72.4x4-liteon.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf) corresponds to: -- TDD pattern `DDDSU`, 2.5ms -- Bandwidth 100MHz -- MTU 1500 -- MTU 9216: v02.00.10 - ##### RU configuration SSH to the unit as user `user`. Write `enable` in the terminal to enter the configuration console; the password should be in the user guide. Use the command `show oru-status` to check the RU status. The output should be similar to: @@ -593,7 +587,15 @@ Once the RU is PTP synced, and RF state and DPD are `Ready`, write `configure te - DU MAC address ... -The configuration mode example: +###### FR1 + +The OAI configuration file [`gnb.sa.band78.273prb.fhi72.4x4-liteon.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf) corresponds to: +- TDD pattern `DDDSU`, 2.5ms +- Bandwidth 100MHz +- MTU 1500 +- MTU 9216: v02.00.10 + +The RU configuration mode example: ```bash compression-bit 9 # set IQ bitwidth for PxSCH/PRACH eAXC_id 4 5 6 7 # set PRACH eAxC IDs @@ -601,6 +603,21 @@ jumboframe 1 # enable jumbo frame ... ``` +###### FR2 + +The OAI configuration file [`gnb.sa.band257.66prb.fhi72.2x2-liteon.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.66prb.fhi72.2x2-liteon.conf) corresponds to: +- TDD pattern `DDDDDDDSUU`, 1.25ms +- Bandwidth 100MHz +- FW v02.00.07 +- DL uses jumbo frame, UL uses standard MTU of 1500 bytes + +The RU configuration mode example: +```bash +compression-bit 8 # set IQ bitwidth for PxSCH/PRACH +eAXC_id 0 1 # set PRACH eAxC IDs +... +``` + #### VVDN LPRU **Version 3.x** diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.66prb.fhi72.2x2-liteon.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.66prb.fhi72.2x2-liteon.conf new file mode 100644 index 0000000000..644c6bd9f2 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.66prb.fhi72.2x2-liteon.conf @@ -0,0 +1,281 @@ +Active_gNBs = ( "inria-gnb"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe99; + cell_type = "CELL_MACRO_GNB"; + + gNB_name = "inria-gnb"; + + // 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 = 1; + + ////////// Physical parameters: + + pdsch_AntennaPorts_XP = 2; + pusch_AntennaPorts = 2; + maxMIMO_layers = 2; + do_CSIRS = 1; + do_SRS = 0; + min_rxtxtime = 4; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # center frequency = 28701.12 MHz + # selected SSB frequency = 28691.04 MHz + absoluteFrequencySSB = 2090683; + dl_frequencyBand = 257; + # frequency point A = 28653.6 MHz + dl_absoluteFrequencyPointA = 2090059; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 3; + dl_carrierBandwidth = 66; + #initialDownlinkBWP + #genericParameters + initialDLBWPlocationAndBandwidth = 17875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 3; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 2; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 257; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 3; + ul_carrierBandwidth = 66; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 17875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 3; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 135; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 15; + preambleReceivedTargetPower = -118; +#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 = 2; +#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; +#one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 3, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + +# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB + msg3_DeltaPreamble = 0; + p0_NominalWithGrant = -90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 1; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 3; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 3; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 3; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = 0; + } + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "172.21.6.4"; }); + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.51"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.51"; + 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; + pusch_FailureThres = 1000; + #ul_bler_target_upper =.02; + #ul_bler_target_lower =.01; + #dl_bler_target_upper =.15; + #dl_bler_target_lower =.05 + set_analog_beamforming = "lophy"; + beam_duration = 1; + beams_per_period = 1; + beam_weights = [1]; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 250; + pucch0_dtx_threshold = 100; + pusch_dtx_threshold = -200; + max_ldpc_iterations = 10; + tx_amp_backoff_dB = 18; + L1_rx_thread_core = 10; + L1_tx_thread_core = 11; + phase_compensation = 1; + +} +); + +RUs = ( +{ + local_rf = "no"; + nb_tx = 2; + nb_rx = 2; + att_tx = 0 + att_rx = 0; + bands = [257]; + nr_scs_for_raster = 3; + max_pdschReferenceSignalPower = -40; + max_rxgain = 60; + #sf_extension = 0; + eNB_instances = [0]; + ru_thread_core = 9; + sl_ahead = 10; + tr_preference = "raw_if4p5"; + do_precoding = 0; +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level = "info"; + hw_log_level = "info"; + phy_log_level = "info"; + mac_log_level = "info"; + rlc_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + ngap_log_level = "info"; + f1ap_log_level = "info"; +}; + +fhi_72 = { + dpdk_devices = ("0000:c1:11.0", "0000:c1:11.1"); # one VF can be used as well + system_core = 6; + io_core = 7; + worker_cores = (8); + ru_addr = ("E8:C7:4F:1E:C7:5B", "E8:C7:4F:1E:C7:5B"); + mtu = 9216; + fh_config = ({ + RunSlotPrbMapBySymbol = 1; + T1a_cp_dl = (110, 111); + T1a_cp_ul = (69, 70); + T1a_up = (30, 64); + Ta4 = (30, 64); + ru_config = { + iq_width = 8; + iq_width_prach = 8; + }; + prach_config = { + eAxC_offset = 0; + kbar = 0; + }; + }); +}; From abbd670e5d9fd88982c16bb82ee12d9447f85d97 Mon Sep 17 00:00:00 2001 From: Aaron van Diepen Date: Tue, 17 Mar 2026 14:02:05 +0100 Subject: [PATCH 20/33] Derive Serving Network Name from SIB1 PLMN Extract MCC and MNC from the SIB1 PLMN identity and store them in the UE NAS context to propogate them to NAS security procedures. Previously, the Serving Network Name (SNN) used during authentication was constructed from the IMSI, implicitly assuming the UE was attached to its home network. In roaming scenarios, this produced an incorrect SNN, causing authentication and key derivation failures. The NAS key derivation functions (transferRES, derive_kausf, derive_kseaf) now build the SNN using the MCC/MNC broadcast by the serving network in SIB1, ensuring that authentication uses the correct serving PLMN during roaming. --- openair2/RRC/NR_UE/rrc_UE.c | 24 ++++++++++++++++++++++ openair3/NAS/NR_UE/nr_nas_msg.c | 35 +++++++++++---------------------- openair3/NAS/NR_UE/nr_nas_msg.h | 1 + 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 65a8bf9432..e7edeca39b 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -486,6 +486,30 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) sib1); LOG_A(NR_RRC, "SIB1 decoded\n"); + + plmn_id_t *plmn_id = malloc_or_fail(sizeof(plmn_id_t)); + + /* selected_plmn_identity is one-indexed */ + AssertFatal(rrc->selected_plmn_identity > 0, "No PLMN selected"); + /* only one PLMN info block is currently supported*/ + NR_PLMN_Identity_t *plmn = sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array[0] + ->plmn_IdentityList.list.array[rrc->selected_plmn_identity - 1]; + + /* Convert MCC */ + plmn_id->mcc = (*plmn->mcc->list.array[0]) * 100 + (*plmn->mcc->list.array[1]) * 10 + (*plmn->mcc->list.array[2]); + + plmn_id->mnc_digit_length = plmn->mnc.list.count; + + /* Convert MNC (2 or 3 digits) */ + if (plmn->mnc.list.count == 3) { + plmn_id->mnc = (*plmn->mnc.list.array[0]) * 100 + (*plmn->mnc.list.array[1]) * 10 + (*plmn->mnc.list.array[2]); + } else { + plmn_id->mnc = (*plmn->mnc.list.array[0]) * 10 + (*plmn->mnc.list.array[1]); + } + + nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id); + nas->sn_id = plmn_id; + nr_timer_start(&SI_info->sib1_timer); SI_info->sib1_validity = true; if (rrc->nrRrcState == RRC_STATE_IDLE_NR) { diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index b52bb982fc..4cfb061cee 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -101,26 +101,13 @@ static fgmm_msg_header_t set_mm_header(fgs_nas_msg_t type, Security_header_t sec return mm_header; } -static void servingNetworkName(uint8_t *msg, char *imsiStr, int mnc_size) +static void servingNetworkName(uint8_t *msg, plmn_id_t *plmn_id) { // SNN-network-identifier in TS 24.501 // TS 24.501: If the MNC of the serving PLMN has two digits, then a zero is added at the beginning. - - // MNC - char mnc[4]; - if (mnc_size == 2) { - snprintf(mnc, sizeof(mnc), "0%c%c", imsiStr[3], imsiStr[4]); - } else { - snprintf(mnc, sizeof(mnc), "%c%c%c", imsiStr[3], imsiStr[4], imsiStr[5]); - } - - // MCC - char mcc[4]; - snprintf(mcc, sizeof(mcc), "%c%c%c", imsiStr[0], imsiStr[1], imsiStr[2]); - int size = 64; - snprintf((char *)msg, size, "5G:mnc%3s.mcc%3s.3gppnetwork.org", mnc, mcc); + snprintf((char *)msg, size, "5G:mnc%03d.mcc%03d.3gppnetwork.org", plmn_id->mnc, plmn_id->mcc); } static const char *print_info(uint8_t id, const text_info_t *array, uint8_t array_size) @@ -505,11 +492,11 @@ static int fill_imeisv(FGSMobileIdentity *mi, const uicc_t *uicc) return 19; } -void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, uicc_t *uicc) +void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, plmn_id_t *plmn_id) { uint8_t S[100] = {0}; S[0] = 0x6B; - servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); + servingNetworkName(S + 1, plmn_id); int netNamesize = strlen((char *)S + 1); S[1 + netNamesize] = (netNamesize & 0xff00) >> 8; S[2 + netNamesize] = (netNamesize & 0x00ff); @@ -548,7 +535,7 @@ void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16 memcpy(output, out + 16, 16); } -void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32], uicc_t *uicc) +void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[32], plmn_id_t *plmn_id) { uint8_t S[100] = {0}; uint8_t key[32] = {0}; @@ -556,7 +543,7 @@ void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[ memcpy(&key[0], ck, 16); memcpy(&key[16], ik, 16); // KEY S[0] = 0x6A; - servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); + servingNetworkName(S + 1, plmn_id); int netNamesize = strlen((char *)S + 1); S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); @@ -570,11 +557,11 @@ void derive_kausf(uint8_t ck[16], uint8_t ik[16], uint8_t sqn[6], uint8_t kausf[ kdf(key, data, 32, kausf); } -void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32], uicc_t *uicc) +void derive_kseaf(uint8_t kausf[32], uint8_t kseaf[32], plmn_id_t *plmn_id) { uint8_t S[100] = {0}; S[0] = 0x6C; // FC - servingNetworkName(S + 1, uicc->imsiStr, uicc->nmc_size); + servingNetworkName(S + 1, plmn_id); int netNamesize = strlen((char *)S + 1); S[1 + netNamesize] = (uint8_t)((netNamesize & 0xff00) >> 8); S[2 + netNamesize] = (uint8_t)(netNamesize & 0x00ff); @@ -641,14 +628,14 @@ static void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) uint8_t ck[16], ik[16]; f2345(nas->uicc->key, rand, resTemp, ck, ik, ak, nas->uicc->opc); - transferRES(ck, ik, resTemp, rand, output, nas->uicc); + transferRES(ck, ik, resTemp, rand, output, nas->sn_id); for (int index = 0; index < 6; index++) { sqn[index] = buf[26 + index]; } - derive_kausf(ck, ik, sqn, kausf, nas->uicc); - derive_kseaf(kausf, kseaf, nas->uicc); + derive_kausf(ck, ik, sqn, kausf, nas->sn_id); + derive_kseaf(kausf, kseaf, nas->sn_id); derive_kamf(kseaf, kamf, 0x0000, nas->uicc); derive_kgnb(kamf, nas->security.nas_count_ul, kgnb); diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index f5e6b4db59..bbd3a13fe5 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -102,6 +102,7 @@ typedef struct { int t3446; /* NAS Key Set Identifier associated to the security context */ uint8_t *ksi; + plmn_id_t *sn_id; } nr_ue_nas_t; nr_ue_nas_t *get_ue_nas_info(module_id_t module_id); From fb685665e2c75cd16490257cf55df2104d3f190a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 18 Mar 2026 08:59:05 +0100 Subject: [PATCH 21/33] vrtsim doc: clarify container requirements --- radio/vrtsim/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/radio/vrtsim/README.md b/radio/vrtsim/README.md index 2cd90e7886..02366c99fc 100644 --- a/radio/vrtsim/README.md +++ b/radio/vrtsim/README.md @@ -8,7 +8,8 @@ interface. The `vrtsim` architecture follows a server-client model: -- **Server (gNB)**: On startup, the server writes a file, default location is +- **Server (gNB)**: On startup, the server writes connection information to a + file as provided in `--vrtsim.descriptor`, default location is `/tmp/vrtsim_connection`. This file contains information required by the client to establish communication. - **Client (UE)**: The client reads this file from, verifies its contents, and uses @@ -31,6 +32,13 @@ Additionally on gNB use `vrtsim.role server` and optionally `vrtsim.timescale ` to set the timescale. Timescale 1.0 is the default and means realtime. +To use `vrtsim` in containers, you have to enable inter-process communication, +and mount the directory of the connection information in a shared volume +between server and clients. For instance, in docker and default +`vrtsim.connection_descriptor`, set `ipc: host` and share the server's and +client's `/tmp` directory through a volume. For an example, refer to +[this docker-compose file](../../ci-scripts/yaml_files/5g_vrtsim_cirdb/docker-compose.yaml). + Channel modelling can be enabled by adding `vrtsim.chanmod 1` to the command line and should work the same as channel modelling in rfsimulator, see rfsimulator [documentation](../rfsimulator/README.md) with a slight difference: From 692cec1a242b6d0d574e76345504fe8247e40cc3 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Sat, 7 Mar 2026 15:46:54 +0100 Subject: [PATCH 22/33] bugfix: use proper pointer --- radio/rfsimulator/simulator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/rfsimulator/simulator.cpp b/radio/rfsimulator/simulator.cpp index 83bdba990a..a2fb0e994d 100644 --- a/radio/rfsimulator/simulator.cpp +++ b/radio/rfsimulator/simulator.cpp @@ -1019,7 +1019,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, signal_energy(static_cast(samplesVoid[0][0]), nsamps)); /* trace only first antenna */ - T(T_USRP_TX_ANT0, T_INT(timestamp), T_BUFFER(samplesVoid[0], (int)sampleToByte(nsamps, 1))); + T(T_USRP_TX_ANT0, T_INT(timestamp), T_BUFFER(samplesVoid[0][0], (int)sampleToByte(nsamps, 1))); return nsamps; } From f4fc7f331fdd1f4466f86eed52f181abdd254806 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 18 Mar 2026 10:01:11 +0100 Subject: [PATCH 23/33] Set rxgain to 0 in vrtsim Set rxgain to 0 in vrtsim to match rfsimulator behavior --- radio/vrtsim/vrtsim.c | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index 36780f3ae6..b33d7970aa 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -1133,5 +1133,6 @@ __attribute__((__visibility__("default"))) int device_init(openair0_device_t *de LOG_A(HW, "VRTSIM: Noise power %d sample value\n", noise_power); init_noise_device(noise_power); } + openair0_cfg->rx_gain[0] = 0; return 0; } From 7232b0a11baedb65cfe95740e4c4f6c2143c601e Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 2 Mar 2026 15:40:37 +0100 Subject: [PATCH 24/33] Adjust FHI72 phytest yaml file Add dpdk-init service into docker-compose.yaml file to execute setup_sriov script during startup. --- ...band77.273prb.fhi72.4x4-vvdn-phytest.conf} | 0 .../xml_files/gnb_phytest_fhi7.2_docker.xml | 7 ----- .../phytest_fhi72/docker-compose.yaml | 29 +++++++++++++++++-- .../phytest_fhi72/setup_sriov_dummy.sh | 18 ++++++------ 4 files changed, 36 insertions(+), 18 deletions(-) rename ci-scripts/conf_files/{gnb.sa.band77.273prb.fhi72.4x4-4L-vvdn.conf => gnb.band77.273prb.fhi72.4x4-vvdn-phytest.conf} (100%) diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-4L-vvdn.conf b/ci-scripts/conf_files/gnb.band77.273prb.fhi72.4x4-vvdn-phytest.conf similarity index 100% rename from ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-4L-vvdn.conf rename to ci-scripts/conf_files/gnb.band77.273prb.fhi72.4x4-vvdn-phytest.conf diff --git a/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker.xml b/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker.xml index 5386ba4d83..309f1784b6 100644 --- a/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker.xml +++ b/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker.xml @@ -25,13 +25,6 @@ Timing phytest 100 MHz 4x4 FHI7.2 tasks - - Custom_Script - Setup sriov and network interfaces for dummy (no RU) - bulbul - - - Pull_Local_Registry Pull Images from Local Registry diff --git a/ci-scripts/yaml_files/phytest_fhi72/docker-compose.yaml b/ci-scripts/yaml_files/phytest_fhi72/docker-compose.yaml index 46fbc24302..15de7ef931 100644 --- a/ci-scripts/yaml_files/phytest_fhi72/docker-compose.yaml +++ b/ci-scripts/yaml_files/phytest_fhi72/docker-compose.yaml @@ -1,4 +1,16 @@ services: + dpdk-init: + image: docker.io/library/oai-dpdk-init:latest + network_mode: host + container_name: dpdk-init + entrypoint: "/tmp/setup_sriov.sh" + privileged: true + devices: + - /dev/vfio:/dev/vfio/ + volumes: + - ./setup_sriov_dummy.sh:/tmp/setup_sriov.sh + - /lib/modules:/lib/modules + - /usr/lib/modules:/usr/lib/modules oai-gnb: image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb-fhi72}:${TAG:-develop} container_name: oai-gnb-phytest @@ -12,11 +24,24 @@ services: devices: - /dev/vfio:/dev/vfio/ volumes: - - ../../conf_files/gnb.sa.band77.273prb.fhi72.4x4-4L-vvdn.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.band77.273prb.fhi72.4x4-vvdn-phytest.conf:/opt/oai-gnb/etc/gnb.conf - /dev/hugepages:/dev/hugepages - cpuset: "8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23" + cpuset: "8-23" + networks: ["public_net"] + depends_on: + dpdk-init: + condition: service_completed_successfully healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s timeout: 5s retries: 5 +networks: + public_net: + driver: bridge + name: ci-physim + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "ci-physim" diff --git a/ci-scripts/yaml_files/phytest_fhi72/setup_sriov_dummy.sh b/ci-scripts/yaml_files/phytest_fhi72/setup_sriov_dummy.sh index c18affb0a9..74a1f627fc 100755 --- a/ci-scripts/yaml_files/phytest_fhi72/setup_sriov_dummy.sh +++ b/ci-scripts/yaml_files/phytest_fhi72/setup_sriov_dummy.sh @@ -19,19 +19,19 @@ IF_NAME=ens1f0np0 C_U_PLANE_MAC_ADD=22:11:55:33:99:55 C_U_PLANE_VLAN=123 MTU=9000 -DPDK_DEVBIND_PREFIX=/home/oaicicd/test/dpdk-stable-22.11.7/bin +DPDK_DEVBIND_PREFIX=/usr/local/bin NUM_VFs=1 -sudo ethtool -G $IF_NAME rx 8160 tx 8160 -sudo sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs" -sudo sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs" +ethtool -G $IF_NAME rx 8160 tx 8160 +sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs" +sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs" C_U_PLANE_PCI=$(pci_addr $IF_NAME 0) # this next 2 lines is for C/U planes -sudo ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU +ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU sleep 1 -sudo modprobe iavf -sudo ${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI -sudo modprobe vfio-pci -sudo ${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI +modprobe iavf +${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI +modprobe vfio-pci +${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI echo "Successfully configured C-PLANE and U-PLANE: - C-PLANE MAC: $C_U_PLANE_MAC_ADD, VLAN: $C_U_PLANE_VLAN, PCI: $C_U_PLANE_PCI" exit 0 From 05273269d25521001f8e6c1435f00f20bf5587f0 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Tue, 3 Mar 2026 10:52:32 +0100 Subject: [PATCH 25/33] CI: Allow to select service for RT stats analysis When running phytest with FHI7.2 in Docker, two services are deployed: dpdk-init and oai-gnb. Previously, AnalyzeRTStatsObject selected the first deployed service for RT stats analysis. Allow to explicitly select the service used for RT stats analysis instead of relying on the first deployed service. --- ci-scripts/cls_containerize.py | 10 ++++++++-- ci-scripts/main.py | 3 ++- ci-scripts/xml_files/gnb_phytest_fhi7.2_docker.xml | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index f1e49bc0a7..fe6b648975 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -789,7 +789,7 @@ class Containerize(): logging.error('\u001B[1m Undeploying objects Failed\u001B[0m') return success - def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds): + def AnalyzeRTStatsObject(self, HTML, node, ctx, thresholds, service=None): logging.info(f'Analyzing realtime stats from server: {node}') yaml = self.yamlPath.strip('/') wd = f'{self.eNBSourceCodePath}/{yaml}' @@ -797,7 +797,13 @@ class Containerize(): with cls_cmd.getConnection(node) as cmd: services = GetDeployedServices(cmd, wd_yaml) - s, _ = services[0] # we simply assume something is deployed, if not Exception will report + if not services: + raise RuntimeError("No deployed docker compose services found") + deployed_services = [s for s, _ in services] + s = service or deployed_services[0] # choose first service if not provided + if s not in deployed_services: + raise RuntimeError(f"Requested service {s} not found among services: {deployed_services}") + logging.info(f"Analyzing deployed service '{s}'") # similar to BuildRunTests(), use docker cp to avoid problems with permissions cmd.run(f'docker compose -f {wd_yaml} cp {s}:/opt/oai-gnb/nrL1_stats.log {wd}/') l1_file = archiveArtifact(cmd, ctx, f"{wd}/nrL1_stats.log") diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 9e1401fcf0..2087c2da5c 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -259,7 +259,8 @@ def ExecuteActionWithParam(action, ctx, node): elif action == 'AnalyzeRTStats_Object': yaml = test.findtext('stats_cfg') - success = CONTAINERS.AnalyzeRTStatsObject(HTML, node, ctx, yaml) + service = test.findtext('service') + success = CONTAINERS.AnalyzeRTStatsObject(HTML, node, ctx, yaml, service) else: logging.warning(f"unknown action {action}, skip step") diff --git a/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker.xml b/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker.xml index 309f1784b6..aa7985ad9d 100644 --- a/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker.xml +++ b/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker.xml @@ -56,6 +56,7 @@ AnalyzeRTStats_Object Analyze Real-Time Stats datalog_rt_stats.100.4x4.fhi72.yaml + oai-gnb bulbul From 858c8b5bdb7f027b7d5f06e7c837b9599faf396d Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 9 Mar 2026 19:24:19 +0100 Subject: [PATCH 26/33] CI: remove unused FHI72 confs --- ci-scripts/ci_infra.yaml | 4 - ...a.band77.273prb.fhi72.4x4.2L-metanoia.conf | 249 ---------------- ...sa.band78.273prb.fhi72.4x4-benetel550.conf | 272 ------------------ .../container_sa_fhi72_metanoia_up2_2x2.xml | 151 ---------- .../sa_fhi_7.2_benetel550_gnb/README.md | 15 - .../docker-compose.yml | 42 --- .../setup_cleanup.sh | 5 - .../setup_sriov_benetel.sh | 22 -- .../sa_fhi_7.2_metanoia_2x2_gnb/README.md | 87 ------ .../docker-compose.yml | 41 --- .../setup_cleanup.sh | 5 - .../setup_sriov_metanoia.sh | 20 -- 12 files changed, 913 deletions(-) delete mode 100644 ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf delete mode 100644 ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf delete mode 100644 ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml delete mode 100644 ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/README.md delete mode 100644 ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml delete mode 100644 ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/setup_cleanup.sh delete mode 100644 ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/setup_sriov_benetel.sh delete mode 100644 ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/README.md delete mode 100644 ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml delete mode 100644 ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_cleanup.sh delete mode 100644 ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_sriov_metanoia.sh diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 837f1edb82..2fa8f6dbc6 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -175,10 +175,6 @@ amarisoft_ue_2x2: InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_aw2s_asue_20MHz_2x2/aw2s-multi-00102-2x2-v2.cfg & TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 NetworkScript: ip netns exec ue1 ip a show dev pdn0 -amarisoft_ue_fhi72: - Host: amariue - InitScript: /root/lteue-linux-2025-03-15/lteue /root/oaicicd/ran_sa_fhi72_asue_2x2_benetel550/fhi72-multi-20897-2x2.cfg & - TermScript: /root/lteue-linux-2025-03-15/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 amarisoft_ue_1: Host: amariue AttachScript: /root/lteue-linux-2025-03-15/ws.js 127.0.0.1:9002 '{"message":"power_on","ue_id":1}' diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf deleted file mode 100644 index 41e9974caf..0000000000 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf +++ /dev/null @@ -1,249 +0,0 @@ -Active_gNBs = ( "oai-du"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; -gNBs = -( - { - ////////// Identification parameters: - gNB_ID = 0xe00; - gNB_name = "oai-du"; - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ( { sst = 1; }); }); - nr_cellid = 1; - - ////////// Physical parameters: - pdsch_AntennaPorts_XP = 2; - pusch_AntennaPorts = 4; - pdsch_AntennaPorts_N1 = 2; - maxMIMO_layers = 2; - do_CSIRS = 1; - do_SRS = 0; - force_UL256qam_off = 1; - - servingCellConfigCommon = ( - { -#spCellConfigCommon - physCellId = 0; -# downlinkConfigCommon - #frequencyInfoDL - # this is 3300.24 + 134*12*30e3 = 3348.48 MHz (5G NR GSCN: 7741) - absoluteFrequencySSB = 649920; #JF maybe we should adjust a bit - dl_frequencyBand = 78; - # this is 3300.24 MHz - dl_absoluteFrequencyPointA = 646724; - #scs-SpecificCarrierList - dl_offstToCarrier = 0; -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - dl_subcarrierSpacing = 1; - dl_carrierBandwidth = 273; - #initialDownlinkBWP - #genericParameters - # this is RBstart=0,L=162 (275*(275-L+1))+(274-RBstart)) - initialDLBWPlocationAndBandwidth = 1099; - # -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - initialDLBWPsubcarrierSpacing = 1; - #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 12; - initialDLBWPsearchSpaceZero = 0; - #uplinkConfigCommon - #frequencyInfoUL - ul_frequencyBand = 78; - #scs-SpecificCarrierList - ul_offstToCarrier = 0; -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - ul_subcarrierSpacing = 1; - ul_carrierBandwidth = 273; - pMax = 20; - #initialUplinkBWP - #genericParameters - initialULBWPlocationAndBandwidth = 1099; -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - initialULBWPsubcarrierSpacing = 1; - #rach-ConfigCommon - #rach-ConfigGeneric - prach_ConfigurationIndex = 148; # JF check this and other PRACH related params -#prach_msg1_FDM -#0 = one, 1=two, 2=four, 3=eight - prach_msg1_FDM = 0; - prach_msg1_FrequencyStart = 0; - zeroCorrelationZoneConfig = 12; - preambleReceivedTargetPower = -96; -#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) - preambleTransMax = 6; -#powerRampingStep -# 0=dB0,1=dB2,2=dB4,3=dB6 - powerRampingStep = 1; -#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; -#one (0..15) 4,8,12,16,...60,64 - ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; -#ra_ContentionResolutionTimer -#(0..7) 8,16,24,32,40,48,56,64 - ra_ContentionResolutionTimer = 7; - rsrp_ThresholdSSB = 19; -#prach-RootSequenceIndex_PR -#1 = 839, 2 = 139 - prach_RootSequenceIndex_PR = 2; - prach_RootSequenceIndex = 1; - # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex - # - msg1_SubcarrierSpacing = 1, -# restrictedSetConfig -# 0=unrestricted, 1=restricted type A, 2=restricted type B - restrictedSetConfig = 0, - msg3_DeltaPreamble = 1; - p0_NominalWithGrant = -90; -# pucch-ConfigCommon setup : -# pucchGroupHopping -# 0 = neither, 1= group hopping, 2=sequence hopping - pucchGroupHopping = 0; - hoppingId = 40; - p0_nominal = -90; - - ssb_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; #6; - nrofDownlinkSlots = 3; #7; - nrofDownlinkSymbols = 6; - nrofUplinkSlots = 1; #2; - nrofUplinkSymbols = 4; - ssPBCH_BlockPower = -10; - } - ); - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - ////////// AMF parameters: - amf_ip_address = ({ ipv4 = "172.21.6.103"; }); - - NETWORK_INTERFACES : - { - GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.18.20"; - GNB_IPV4_ADDRESS_FOR_NGU = "172.21.18.20"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - } -); -MACRLCs = ( -{ - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 220; - pucch_TargetSNRx10 = 220; - 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 = 130; - pucch0_dtx_threshold = 80; - pusch_dtx_threshold = 10; - max_ldpc_iterations = 10; - tx_amp_backoff_dB = 12; #9; needs to match O-RU configuration # JF important to check - L1_rx_thread_core = 3; - L1_tx_thread_core = 4; # relevant after merge of l1_tx_thread - phase_compensation = 0; # needs to match O-RU configuration # JF to be tested -} -); -RUs = ( -{ - local_rf = "no"; - nb_tx = 4; - nb_rx = 4; - att_tx = 0 - att_rx = 0; - bands = [78]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 75; - sf_extension = 0; - eNB_instances = [0]; - ru_thread_core = 6; - sl_ahead = 10; #5; - tr_preference = "raw_if4p5"; # important: activate FHI7.2 - do_precoding = 0; # needs to match O-RU configuration -} -); - -security = { - # preferred ciphering algorithms - # the first one of the list that an UE supports in chosen - # valid values: nea0, nea1, nea2, nea3 - ciphering_algorithms = ( "nea0" ); - - # preferred integrity algorithms - # the first one of the list that an UE supports in chosen - # valid values: nia0, nia1, nia2, nia3 - integrity_algorithms = ( "nia2", "nia0" ); - - # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter - # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' - drb_ciphering = "yes"; - drb_integrity = "no"; -}; - -log_config : -{ - global_log_level ="info"; - hw_log_level ="info"; - phy_log_level ="info"; - mac_log_level ="info"; - rlc_log_level ="info"; - pdcp_log_level ="info"; - rrc_log_level ="info"; - ngap_log_level ="info"; - f1ap_log_level ="info"; -}; - -fhi_72 = { - dpdk_devices = ("0000:c3:11.0", "0000:c3:11.1"); - dpdk_iova_mode = "VA"; - system_core = 0; - io_core = 1; - worker_cores = (2); - ru_addr = ("00:E0:0C:00:AE:06", "00:E0:0C:00:AE:06"); - mtu = 9000; - fh_config = ({ - T1a_cp_dl = (285, 470); - T1a_cp_ul = (285, 429); - T1a_up = (125, 350); - Ta4 = (110, 180); - ru_config = { - iq_width = 9; - iq_width_prach = 9; - }; - }); -}; - diff --git a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf b/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf deleted file mode 100644 index 885f561bec..0000000000 --- a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf +++ /dev/null @@ -1,272 +0,0 @@ -Active_gNBs = ( "gNB-OAI"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -gNBs = -( - { - ////////// Identification parameters: - gNB_ID = 0xe00; - gNB_name = "gNB-OAI"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ( { sst = 1; }); }); - - nr_cellid = 1; - - ////////// Physical parameters: - - pdsch_AntennaPorts_XP = 2; - pdsch_AntennaPorts_N1 = 1; - maxMIMO_layers = 2; - pusch_AntennaPorts = 4; - do_CSIRS = 1; - do_SRS = 0; - # force_UL256qam_off = 1; - - servingCellConfigCommon = ( - { - #spCellConfigCommon - - physCellId = 0; - # n_TimingAdvanceOffset = 0; -# downlinkConfigCommon - #frequencyInfoDL - # center frequency = 3350.01 MHz - # selected SSB frequency = 3349.92 MHz - absoluteFrequencySSB = 623328; - dl_frequencyBand = 78; - # frequency point A = 3300.87 MHz - dl_absoluteFrequencyPointA = 620052; - #scs-SpecificCarrierList - dl_offstToCarrier = 0; -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - dl_subcarrierSpacing = 1; - dl_carrierBandwidth = 273; - #initialDownlinkBWP - #genericParameters - initialDLBWPlocationAndBandwidth = 1099; #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 = 273; - pMax = 23; - #initialUplinkBWP - #genericParameters - initialULBWPlocationAndBandwidth = 1099; -# subcarrierSpacing -# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 - initialULBWPsubcarrierSpacing = 1; - #rach-ConfigCommon - #rach-ConfigGeneric - prach_ConfigurationIndex = 152; -#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 = 1; -#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; -#one (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_PositionsInBurst_Bitmap = 0x1; - -# 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 = -15; - } - - ); - - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - - ////////// AMF parameters: - amf_ip_address = ({ ipv4 = "172.21.6.103"; }); - - NETWORK_INTERFACES : - { - GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.18.20"; - GNB_IPV4_ADDRESS_FOR_NGU = "172.21.18.20"; - GNB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - } -); - -MACRLCs = ( -{ - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 100; - pucch_TargetSNRx10 = 200; - dl_bler_target_upper = .35; - dl_bler_target_lower = .15; - ul_bler_target_upper = .35; - ul_bler_target_lower = .15; - pusch_FailureThres = 1000; - ul_max_mcs = 28; -} -); - -L1s = ( -{ - num_cc = 1; - tr_n_preference = "local_mac"; - prach_dtx_threshold = 90; - pucch0_dtx_threshold = 80; - pusch_dtx_threshold = 10; - max_ldpc_iterations = 15; - tx_amp_backoff_dB = 12; # needs to match O-RU configuration - L1_rx_thread_core = 3; - L1_tx_thread_core = 4; - phase_compensation = 0; # needs to match O-RU configuration -} -); - -RUs = ( -{ - local_rf = "no"; - nb_tx = 4; - nb_rx = 4; - att_tx = 0; - att_rx = 0; - bands = [78]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 75; - sf_extension = 0; - eNB_instances = [0]; - ru_thread_core = 5; - sl_ahead = 10; - tr_preference = "raw_if4p5"; # important: activate FHI7.2 - do_precoding = 0; # needs to match O-RU configuration -} -); - -security = { - # preferred ciphering algorithms - # the first one of the list that an UE supports in chosen - # valid values: nea0, nea1, nea2, nea3 - ciphering_algorithms = ( "nea0" ); - - # preferred integrity algorithms - # the first one of the list that an UE supports in chosen - # valid values: nia0, nia1, nia2, nia3 - integrity_algorithms = ( "nia2", "nia0" ); - - # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter - # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' - drb_ciphering = "yes"; - drb_integrity = "no"; -}; - -log_config : -{ - global_log_level = "info"; - hw_log_level = "info"; - phy_log_level = "info"; - mac_log_level = "info"; - rlc_log_level = "info"; - pdcp_log_level = "info"; - rrc_log_level = "info"; - ngap_log_level = "info"; - f1ap_log_level = "info"; -}; - -fhi_72 = { - dpdk_devices = ("0000:c3:11.0", "0000:c3:11.1"); - system_core = 0; - io_core = 1; - worker_cores = (2); - ru_addr = ("70:b3:d5:e1:5b:81", "70:b3:d5:e1:5b:81"); - mtu = 9216; - fh_config = ({ - 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; - }; - }); -}; diff --git a/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml b/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml deleted file mode 100644 index 97037157b4..0000000000 --- a/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml +++ /dev/null @@ -1,151 +0,0 @@ - - - test-5g-fhi72-metanoia-2x2 - 100 MHz TDD SA METANOIA - tasks - - - Custom_Script - Setup sriov and network interfaces Metanoia - cacofonix - - - - - Pull_Local_Registry - Pull Images from Local Registry - cacofonix - oai-gnb-fhi72 - - - - Create_Workspace - Create new Workspace for server 0 - cacofonix - - - - Deploy_Object - Deploy gNB (TDD/Band78/100MHz/Metanoia) in a container - cacofonix - ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb - - - - Attach_UE - Attach UE - up2-fhi72 - - - - Ping - Ping: 100 pings in 10 sec - up2-fhi72 - oc-cn5g-20897 - -c 100 -i 0.1 - 1 - 15 - - - - Iperf - iperf (DL/570Mbps/UDP)(30 sec) - -u -b 570M -t 30 -R - up2-fhi72 - 20 - 80 - balanced - oc-cn5g-20897 - - - - Iperf - iperf (UL/100Mbps/UDP)(30 sec) - -u -b 100M -t 30 - up2-fhi72 - 20 - 80 - balanced - oc-cn5g-20897 - - - - Iperf - iperf (DL/TCP)(30 sec) - -t 30 -R - up2-fhi72 - 80 - oc-cn5g-20897 - - - - Iperf - iperf (UL/TCP)(30 sec) - -t 30 - up2-fhi72 - 80 - oc-cn5g-20897 - - - - Detach_UE - true - Detach UE - up2-fhi72 - - - - IdleSleep - Sleep - 5 - - - - Undeploy_Object - true - Undeploy gNB - cacofonix - ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb - - oai-gnb=EndsWithBye - - - - - Clean_Test_Server_Images - true - Clean Test Images on Test Server - cacofonix - oai-gnb-fhi72 - - - - Custom_Script - true - Set CPU to idle state, set kernel parameters to default values - cacofonix - - - - diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/README.md b/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/README.md deleted file mode 100644 index c9cf235bb2..0000000000 --- a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/README.md +++ /dev/null @@ -1,15 +0,0 @@ - - - - - -
- - - - - - OAI O-RAN 7.2 Front-haul Docker Compose -
- -For instructions on OAI gNB Docker deployment with FH 7.2 RU, please refer to the [README](../sa_fhi_7.2_vvdn_gnb/README.md). diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml deleted file mode 100644 index 8c38739994..0000000000 --- a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/docker-compose.yml +++ /dev/null @@ -1,42 +0,0 @@ -services: - oai-gnb: - image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop} - cap_add: - - SYS_ADMIN - - IPC_LOCK - - SYS_NICE - cap_drop: - - ALL - container_name: oai-gnb - environment: - TZ: Europe/Paris - USE_ADDITIONAL_OPTIONS: --thread-pool 6,7,8,9 - devices: - - /dev/vfio:/dev/vfio/ - volumes: - - ../../conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf:/opt/oai-gnb/etc/gnb.conf - - /dev/hugepages:/dev/hugepages - # Please change these values based on your system - cpuset: "0,1,2,3,4,5,6,7,8,9" - networks: - oai-net: - ipv4_address: 172.21.18.20 - healthcheck: - test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" - start_period: 15s - start_interval: 500ms - interval: 5s - timeout: 5s - retries: 10 -networks: - oai-net: - driver: macvlan - name: oai-net - ipam: - config: - - subnet: "172.21.16.0/22" - ip_range: "172.21.18.20/32" - gateway: "172.21.19.254" - driver_opts: - com.docker.network.bridge.name: "oai-net" - parent: ens7f0 diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/setup_cleanup.sh b/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/setup_cleanup.sh deleted file mode 100644 index 9a06336acc..0000000000 --- a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/setup_cleanup.sh +++ /dev/null @@ -1,5 +0,0 @@ -set -e -sudo cpupower idle-set -E > /dev/null -sudo sysctl kernel.sched_rt_runtime_us=950000 -sudo sysctl kernel.timer_migration=1 -exit 0 diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/setup_sriov_benetel.sh b/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/setup_sriov_benetel.sh deleted file mode 100644 index 1bcf941ae0..0000000000 --- a/ci-scripts/yaml_files/sa_fhi_7.2_benetel550_gnb/setup_sriov_benetel.sh +++ /dev/null @@ -1,22 +0,0 @@ -set -e -sudo cpupower idle-set -D 0 > /dev/null -sudo sysctl kernel.sched_rt_runtime_us=-1 -sudo sysctl kernel.timer_migration=0 -sudo ethtool -G ens7f1 rx 8160 -sudo ethtool -G ens7f1 tx 8160 -sudo ifconfig ens7f1 mtu 9216 -sudo sh -c 'echo 0 > /sys/class/net/ens7f1/device/sriov_numvfs' -sudo sh -c 'echo 2 > /sys/class/net/ens7f1/device/sriov_numvfs' -sudo modprobe -r iavf -sudo modprobe iavf -# this next 2 lines is for C/U planes -sudo ip link set ens7f1 vf 0 mac 00:11:22:33:44:66 vlan 3 qos 0 spoofchk off mtu 9216 -sudo ip link set ens7f1 vf 1 mac 00:11:22:33:44:67 vlan 3 qos 0 spoofchk off mtu 9216 -sleep 1 -# These are the DPDK bindings for C/U-planes on vlan 3 -sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.0 -sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.1 -sudo modprobe vfio-pci -sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.0 -sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.1 -exit 0 diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/README.md b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/README.md deleted file mode 100644 index 53d4312787..0000000000 --- a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/README.md +++ /dev/null @@ -1,87 +0,0 @@ - - - - - -
- - - - - - OAI O-RAN 7.2 Front-haul Docker Compose -
- -![Docker deploy 7.2](../../../doc/images/docker-deploy-oai-7-2.png) - -This docker-compose is designed to use `OAI-gNB` with a 7.2 compatible Radio Unit. Before using this docker compose you have to configure -the host machine as per the [ORAN_FHI7.2_Tutorial](../../../doc/ORAN_FHI7.2_Tutorial.md). The container image used by the docker compose file is tested only on `Ubuntu 22.04` and `RHEL 9.4` docker host. - -## Build Image (Optional) - -Refer to [OAI Docker/Podman Build and Usage Procedures](../../../docker/README.md) - -## Configure Networking - -### SR-IOV Virtual Functions (VFs) - -In docker-compose environment there is no automated method -to configure the VFs on the fly. The user will have to manually configure -C/U plane VFs before starting the container `OAI-gNB`. - -You can follow the step -[configure-network-interfaces-and-dpdk-vfs](../../../doc/ORAN_FHI7.2_Tutorial.md#configure-network-interfaces-and-dpdk-vfs). - -### Interface towards AMF (N2) - -For `N2` interface we are using `macvlan` driver of docker. - -You can use the `bridge` driver, in situation - -- When the core network is running on the same machine -- or different machine but you have configured -needed `ip route` and forwarding to access the core network from RAN host. - -To configure docker `macvlan` network -you need to choose `ipam.config` and `driver_opts.parent` are per your environment - -``` - oai-net: - driver: macvlan - name: oai-net - ipam: - config: - - subnet: "172.21.16.0/22" - ip_range: "172.21.18.20/32" - gateway: "172.21.19.254" - driver_opts: - com.docker.network.bridge.name: "oai-net" - parent: ens7f0 -``` - -To configure `bridge` network you need to choose `ipam.config.subnet` as per your environment. - -``` - oai-net: - driver: bridge - name: oai-net - ipam: - config: - - subnet: 192.168.72.128/26 - driver_opts: - com.docker.network.bridge.name: "oai-net" -``` - -## Deploy OAI-gNB Container - -The [configuration file](../../conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf) used by docker compose is configured for Metanoia RU. - -```bash -docker-compose up -d -``` - -To check the logs - -```bash -docker logs oai-gnb -f -``` diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml deleted file mode 100644 index 3e29c33ff9..0000000000 --- a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/docker-compose.yml +++ /dev/null @@ -1,41 +0,0 @@ -services: - oai-gnb: - image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop} - cap_add: - - IPC_LOCK - - SYS_NICE - cap_drop: - - ALL - container_name: oai-gnb - environment: - TZ: Europe/Paris - USE_ADDITIONAL_OPTIONS: --thread-pool 7,8,9,10,11,12 - devices: - - /dev/vfio:/dev/vfio/ - volumes: - - ../../conf_files/gnb.sa.band77.273prb.fhi72.4x4.2L-metanoia.conf:/opt/oai-gnb/etc/gnb.conf - - /dev/hugepages:/dev/hugepages - # Please change these values based on your system - cpuset: "0,1,2,3,4,5,6,7,8,9,10,11,12" - networks: - oai-net: - ipv4_address: 172.21.18.20 - healthcheck: - test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" - start_period: 15s - start_interval: 500ms - interval: 5s - timeout: 5s - retries: 10 -networks: - oai-net: - driver: macvlan - name: oai-net - ipam: - config: - - subnet: "172.21.16.0/22" - ip_range: "172.21.18.20/32" - gateway: "172.21.19.254" - driver_opts: - com.docker.network.bridge.name: "oai-net" - parent: ens7f0 diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_cleanup.sh b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_cleanup.sh deleted file mode 100644 index 9a06336acc..0000000000 --- a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_cleanup.sh +++ /dev/null @@ -1,5 +0,0 @@ -set -e -sudo cpupower idle-set -E > /dev/null -sudo sysctl kernel.sched_rt_runtime_us=950000 -sudo sysctl kernel.timer_migration=1 -exit 0 diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_sriov_metanoia.sh b/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_sriov_metanoia.sh deleted file mode 100644 index 1d7215b70a..0000000000 --- a/ci-scripts/yaml_files/sa_fhi_7.2_metanoia_2x2_gnb/setup_sriov_metanoia.sh +++ /dev/null @@ -1,20 +0,0 @@ -set -e -sudo cpupower idle-set -D 0 > /dev/null -sudo sysctl kernel.sched_rt_runtime_us=-1 -sudo sysctl kernel.timer_migration=0 -sudo ethtool -G ens7f1 rx 8160 tx 8160 -sudo sh -c 'echo 0 > /sys/class/net/ens7f1/device/sriov_numvfs' -sudo sh -c 'echo 3 > /sys/class/net/ens7f1/device/sriov_numvfs' -sudo modprobe -r iavf -sudo modprobe iavf -# this next 2 lines is for C/U planes -sudo ip link set ens7f1 vf 0 mac 00:11:22:33:44:55 vlan 3 spoofchk off mtu 9000 -sudo ip link set ens7f1 vf 1 mac 00:11:22:33:44:54 vlan 3 spoofchk off mtu 9000 -sleep 1 -# These are the DPDK bindings for C/U-planes on vlan 1 -sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.0 -sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.1 -sudo modprobe vfio-pci -sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.0 -sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.1 -exit 0 From b400d1ee3f1491070d72511252182ca16c573d33 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 9 Mar 2026 19:43:16 +0100 Subject: [PATCH 27/33] CI: Update FHI72 VVDN deployment files - Introduce dpdk-init service for SR-IOV initialization within the container - Execute script to enable low-latency RT performance (restored after tests) --- .../gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf | 4 +- .../xml_files/container_sa_fhi72_vvdn_up2.xml | 4 +- .../sa_fhi_7.2_vvdn_gnb/docker-compose.yml | 17 +++++- .../sa_fhi_7.2_vvdn_gnb/setup_cleanup.sh | 0 .../sa_fhi_7.2_vvdn_gnb/setup_config.sh | 4 ++ .../sa_fhi_7.2_vvdn_gnb/setup_sriov_vvdn.sh | 52 ++++++++++++------- 6 files changed, 58 insertions(+), 23 deletions(-) mode change 100644 => 100755 ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_cleanup.sh create mode 100755 ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_config.sh mode change 100644 => 100755 ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_sriov_vvdn.sh diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf index c01c9afc79..f2974e1950 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf @@ -245,12 +245,12 @@ log_config : }; fhi_72 = { - dpdk_devices = ("0000:c3:11.0", "0000:c3:11.1"); + dpdk_devices = ("0000:c3:11.0"); dpdk_iova_mode = "VA"; system_core = 0; io_core = 1; worker_cores = (2); - ru_addr = ("98:ae:71:04:83:e3", "98:ae:71:04:83:e3"); + ru_addr = ("98:ae:71:04:83:e3"); mtu = 9216; fh_config = ({ T1a_cp_dl = (285, 470); diff --git a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml index d8548077fd..7dc7e49b3c 100644 --- a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml +++ b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml @@ -27,9 +27,9 @@ Custom_Script - Setup sriov and network interfaces VVDN + Configure system for low-latency RT performance cacofonix - + diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml index 2e6c044fcb..8c47dd6683 100644 --- a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/docker-compose.yml @@ -1,4 +1,16 @@ services: + dpdk-init: + image: docker.io/library/oai-dpdk-init:latest + network_mode: host + container_name: dpdk-init + entrypoint: "/tmp/setup_sriov.sh" + privileged: true + devices: + - /dev/vfio:/dev/vfio/ + volumes: + - ./setup_sriov_vvdn.sh:/tmp/setup_sriov.sh + - /lib/modules:/lib/modules + - /usr/lib/modules:/usr/lib/modules oai-gnb: image: ${REGISTRY-oaisoftwarealliance/}oai-gnb-fhi72:${TAG:-develop} cap_add: @@ -16,10 +28,13 @@ services: - ../../conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf:/opt/oai-gnb/etc/gnb.conf - /dev/hugepages:/dev/hugepages # Please change these values based on your system - cpuset: "0,1,2,3,4,5,6,7,8,9,10,11,12" + cpuset: "0-12" networks: oai-net: ipv4_address: 172.21.18.20 + depends_on: + dpdk-init: + condition: service_completed_successfully healthcheck: test: /bin/bash -c "/opt/oai-gnb/bin/check-prach-io.sh" start_period: 15s diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_cleanup.sh b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_cleanup.sh old mode 100644 new mode 100755 diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_config.sh b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_config.sh new file mode 100755 index 0000000000..8850720d5c --- /dev/null +++ b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_config.sh @@ -0,0 +1,4 @@ +set -e +sudo cpupower idle-set -D 0 > /dev/null +sudo sysctl kernel.sched_rt_runtime_us=-1 +sudo sysctl kernel.timer_migration=0 diff --git a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_sriov_vvdn.sh b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_sriov_vvdn.sh old mode 100644 new mode 100755 index 2b7a512f83..c600550518 --- a/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_sriov_vvdn.sh +++ b/ci-scripts/yaml_files/sa_fhi_7.2_vvdn_gnb/setup_sriov_vvdn.sh @@ -1,21 +1,37 @@ -set -e -sudo cpupower idle-set -D 0 > /dev/null -sudo sysctl kernel.sched_rt_runtime_us=-1 -sudo sysctl kernel.timer_migration=0 -sudo ethtool -G ens7f1 rx 8160 -sudo ethtool -G ens7f1 tx 8160 -sudo sh -c 'echo 0 > /sys/class/net/ens7f1/device/sriov_numvfs' -sudo sh -c 'echo 2 > /sys/class/net/ens7f1/device/sriov_numvfs' -sudo modprobe -r iavf -sudo modprobe iavf +#!/bin/sh +set -eu + +pci_addr() +{ + PF_IF=$1 + VF_INDEX=$2 + SYSFS_PATH="/sys/class/net/${PF_IF}/device/virtfn${VF_INDEX}" + + if [ ! -e "$SYSFS_PATH" ]; then + echo "VF $VF_INDEX not found for interface $PF_IF" + exit 1 + fi + PCI_ADDR=$(basename "$(readlink "$SYSFS_PATH")") + echo "$PCI_ADDR" +} +IF_NAME=ens7f1 +## O-DU C Plane MAC ADDR and VLAN +C_U_PLANE_MAC_ADD=76:76:64:6e:00:01 +C_U_PLANE_VLAN=4 +MTU=9000 +DPDK_DEVBIND_PREFIX=/usr/local/bin +NUM_VFs=1 +ethtool -G $IF_NAME rx 8160 tx 8160 +sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs" +sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs" +C_U_PLANE_PCI=$(pci_addr $IF_NAME 0) # this next 2 lines is for C/U planes -sudo ip link set ens7f1 vf 0 mac 76:76:64:6e:00:01 vlan 4 spoofchk off mtu 9216 -sudo ip link set ens7f1 vf 1 mac 76:76:64:6e:00:00 vlan 4 spoofchk off mtu 9216 +ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU sleep 1 -# These are the DPDK bindings for C/U-planes on vlan 4 -sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.0 -sudo /usr/local/bin/dpdk-devbind.py --unbind c3:11.1 -sudo modprobe vfio-pci -sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.0 -sudo /usr/local/bin/dpdk-devbind.py --bind vfio-pci c3:11.1 +modprobe iavf +${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI +modprobe vfio-pci +${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI +echo "Successfully configured C-PLANE and U-PLANE: + - C-PLANE MAC: $C_U_PLANE_MAC_ADD, VLAN: $C_U_PLANE_VLAN, PCI: $C_U_PLANE_PCI" exit 0 From a6687b60402d1c5a8d44e0aa77bed385d08d6ed7 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 9 Mar 2026 21:58:27 +0100 Subject: [PATCH 28/33] CI: Add FHI72 2x2 phytest on cacofonix --- ...alog_rt_stats.100.2x2.fhi72.cacofonix.yaml | 28 ++++++ .../gnb_phytest_fhi7.2_docker_cacofonix.xml | 97 +++++++++++++++++++ .../docker-compose.yaml | 47 +++++++++ .../phytest_fhi72_cacofonix/setup_cleanup.sh | 5 + .../phytest_fhi72_cacofonix/setup_config.sh | 4 + .../setup_sriov_dummy.sh | 38 ++++++++ 6 files changed, 219 insertions(+) create mode 100644 ci-scripts/datalog_rt_stats.100.2x2.fhi72.cacofonix.yaml create mode 100644 ci-scripts/xml_files/gnb_phytest_fhi7.2_docker_cacofonix.xml create mode 100644 ci-scripts/yaml_files/phytest_fhi72_cacofonix/docker-compose.yaml create mode 100755 ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_cleanup.sh create mode 100755 ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_config.sh create mode 100755 ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_sriov_dummy.sh diff --git a/ci-scripts/datalog_rt_stats.100.2x2.fhi72.cacofonix.yaml b/ci-scripts/datalog_rt_stats.100.2x2.fhi72.cacofonix.yaml new file mode 100644 index 0000000000..de50c38a8e --- /dev/null +++ b/ci-scripts/datalog_rt_stats.100.2x2.fhi72.cacofonix.yaml @@ -0,0 +1,28 @@ +#this is a configuration file +#used to build real time processing statistics +#for 5G NR phy test (gNB terminate) +Title : Processing Time (us) from datalog_rt_stats.4x4.fhi72.yaml +ColNames : + - Metric + - Average; Max; Count + - Average vs Reference Deviation (Reference Value; Acceptability Deviation Threshold) +Ref : + tx_fhaul : 73.0 + feptx_prec (per port, half_slot) : 46.0 + L1 Tx processing : 371.7 + DLSCH encoding : 196.9 + L1 Rx processing : 578.0 + UL segments decoding : 81.2 + UL Indication : 0.4 + Slot Indication : 14.3 + PUSCH inner-receiver : 739.4 +DeviationThreshold : + tx_fhaul : 0.25 + feptx_prec (per port, half_slot) : 0.25 + L1 Tx processing : 0.25 + DLSCH encoding : 0.25 + L1 Rx processing : 0.25 + UL segments decoding : 0.25 + UL Indication : 1.00 + Slot Indication : 0.50 + PUSCH inner-receiver : 0.25 diff --git a/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker_cacofonix.xml b/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker_cacofonix.xml new file mode 100644 index 0000000000..092239ff6f --- /dev/null +++ b/ci-scripts/xml_files/gnb_phytest_fhi7.2_docker_cacofonix.xml @@ -0,0 +1,97 @@ + + + gNB-PHY-Test-100-4x4-FHI72 + Timing phytest 100 MHz 4x4 FHI7.2 + tasks + + + Custom_Script + Configure system for low-latency RT performance + cacofonix + + + + + Pull_Local_Registry + Pull Images from Local Registry + cacofonix + oai-gnb-fhi72 + + + + Create_Workspace + Create new Workspace + cacofonix + + + + Deploy_Object + Initialize gNB FHI7.2 + cacofonix + ci-scripts/yaml_files/phytest_fhi72_cacofonix + oai-gnb + + + + IdleSleep + Sleep + 60 + + + + AnalyzeRTStats_Object + Analyze Real-Time Stats + datalog_rt_stats.100.2x2.fhi72.cacofonix.yaml + oai-gnb + cacofonix + + + + Undeploy_Object + cacofonix + true + Terminate gNB + ci-scripts/yaml_files/phytest_fhi72_cacofonix + + oai-gnb=EndsWithBye + + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + cacofonix + oai-gnb-fhi72 + + + + Custom_Script + true + Set CPU to idle state, set kernel parameters to default values + cacofonix + + + + diff --git a/ci-scripts/yaml_files/phytest_fhi72_cacofonix/docker-compose.yaml b/ci-scripts/yaml_files/phytest_fhi72_cacofonix/docker-compose.yaml new file mode 100644 index 0000000000..87330524a0 --- /dev/null +++ b/ci-scripts/yaml_files/phytest_fhi72_cacofonix/docker-compose.yaml @@ -0,0 +1,47 @@ +services: + dpdk-init: + image: docker.io/library/oai-dpdk-init:latest + network_mode: host + container_name: dpdk-init + entrypoint: "/tmp/setup_sriov.sh" + privileged: true + devices: + - /dev/vfio:/dev/vfio/ + volumes: + - ./setup_sriov_dummy.sh:/tmp/setup_sriov.sh + - /lib/modules:/lib/modules + - /usr/lib/modules:/usr/lib/modules + oai-gnb: + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb-fhi72}:${TAG:-develop} + container_name: oai-gnb-phytest + cap_add: + - IPC_LOCK + - SYS_NICE + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: --phy-test -q -M 273 -m 27 -l 2 -D 231 -T 273 -t 16 -L 2 -U 528 --log_config.global_log_options level,nocolor,time --thread-pool 7,8,9,10,11,12 + devices: + - /dev/vfio:/dev/vfio/ + volumes: + - ../../conf_files/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf:/opt/oai-gnb/etc/gnb.conf + - /dev/hugepages:/dev/hugepages + cpuset: "0-12" + networks: ["public_net"] + depends_on: + dpdk-init: + condition: service_completed_successfully + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 +networks: + public_net: + driver: bridge + name: ci-physim + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "ci-physim" diff --git a/ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_cleanup.sh b/ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_cleanup.sh new file mode 100755 index 0000000000..9a06336acc --- /dev/null +++ b/ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_cleanup.sh @@ -0,0 +1,5 @@ +set -e +sudo cpupower idle-set -E > /dev/null +sudo sysctl kernel.sched_rt_runtime_us=950000 +sudo sysctl kernel.timer_migration=1 +exit 0 diff --git a/ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_config.sh b/ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_config.sh new file mode 100755 index 0000000000..8850720d5c --- /dev/null +++ b/ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_config.sh @@ -0,0 +1,4 @@ +set -e +sudo cpupower idle-set -D 0 > /dev/null +sudo sysctl kernel.sched_rt_runtime_us=-1 +sudo sysctl kernel.timer_migration=0 diff --git a/ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_sriov_dummy.sh b/ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_sriov_dummy.sh new file mode 100755 index 0000000000..9704fc4a42 --- /dev/null +++ b/ci-scripts/yaml_files/phytest_fhi72_cacofonix/setup_sriov_dummy.sh @@ -0,0 +1,38 @@ +#!/bin/sh +set -eu + +pci_addr() +{ + PF_IF=$1 + VF_INDEX=$2 + SYSFS_PATH="/sys/class/net/${PF_IF}/device/virtfn${VF_INDEX}" + + if [ ! -e "$SYSFS_PATH" ]; then + echo "VF $VF_INDEX not found for interface $PF_IF" + exit 1 + fi + PCI_ADDR=$(basename "$(readlink "$SYSFS_PATH")") + echo "$PCI_ADDR" +} +IF_NAME=ens7f1 +## O-DU C Plane MAC ADDR and VLAN +C_U_PLANE_MAC_ADD=22:11:55:33:99:55 +C_U_PLANE_VLAN=123 +MTU=9000 +DPDK_DEVBIND_PREFIX=/usr/local/bin +NUM_VFs=1 +ethtool -G $IF_NAME rx 8160 tx 8160 +sh -c "echo 0 > /sys/class/net/$IF_NAME/device/sriov_numvfs" +sh -c "echo $NUM_VFs > /sys/class/net/$IF_NAME/device/sriov_numvfs" +C_U_PLANE_PCI=$(pci_addr $IF_NAME 0) +# this next 2 lines is for C/U planes +ip link set $IF_NAME vf 0 mac $C_U_PLANE_MAC_ADD vlan $C_U_PLANE_VLAN spoofchk off mtu $MTU +sleep 1 +modprobe iavf +${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --unbind $C_U_PLANE_PCI +modprobe vfio-pci +${DPDK_DEVBIND_PREFIX}/dpdk-devbind.py --bind vfio-pci $C_U_PLANE_PCI +echo "Successfully configured C-PLANE and U-PLANE: + - C-PLANE MAC: $C_U_PLANE_MAC_ADD, VLAN: $C_U_PLANE_VLAN, PCI: $C_U_PLANE_PCI" +exit 0 + From 8aebe7c423b2a6b88894a72486dae433fef24b0e Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 18 Mar 2026 12:20:48 +0100 Subject: [PATCH 29/33] further cleanup since not using NB_ANTENNAS_TX/RX in 5G code --- executables/nr-ru.c | 6 ------ executables/nr-ue-ru.c | 6 ------ openair1/PHY/defs_nr_UE.h | 1 - radio/fhi_72/oran_isolate.h | 1 - 4 files changed, 14 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 4dd7a23d39..cf9541df16 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1459,13 +1459,7 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg) } /* strcmp(local_rf, "yes") != 0 */ ru->nb_tx = *param[RU_NB_TX_IDX].uptr; - AssertFatal(ru->nb_tx <= NB_ANTENNAS_TX, - "Config file has %d TX antennas set, but the compile time max value in NB_ANTENNAS_TX\n", - ru->nb_tx); ru->nb_rx = *param[RU_NB_RX_IDX].uptr; - AssertFatal(ru->nb_rx <= NB_ANTENNAS_RX, - "Config file has %d RX antennas set, but the compile time max value in NB_ANTENNAS_RX\n", - ru->nb_rx); ru->att_tx = *param[RU_ATT_TX_IDX].uptr; ru->att_rx = *param[RU_ATT_RX_IDX].uptr; ru->if_frequency = *param[RU_IF_FREQUENCY].u64ptr; diff --git a/executables/nr-ue-ru.c b/executables/nr-ue-ru.c index 2e082b1e88..8706b00938 100644 --- a/executables/nr-ue-ru.c +++ b/executables/nr-ue-ru.c @@ -211,12 +211,6 @@ void nrue_set_ru_params(configmodule_interface_t *cfg) if (RUParamList.numelt <= 0) { nrue_ru_count = 1; nrue_rus = calloc_or_fail(nrue_ru_count, sizeof(nrUE_RU_params_t)); - AssertFatal(get_nrUE_params()->nb_antennas_tx <= NB_ANTENNAS_TX, - "Config file has %d TX antennas set, but the compile time max value in NB_ANTENNAS_TX\n", - get_nrUE_params()->nb_antennas_tx); - AssertFatal(get_nrUE_params()->nb_antennas_rx <= NB_ANTENNAS_RX, - "Config file has %d RX antennas set, but the compile time max value in NB_ANTENNAS_RX\n", - get_nrUE_params()->nb_antennas_tx); nrue_rus[0] = (nrUE_RU_params_t){.nb_tx = get_nrUE_params()->nb_antennas_tx, .nb_rx = get_nrUE_params()->nb_antennas_rx, .att_tx = get_nrUE_params()->tx_gain, diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index eb0403a2ba..256bf0907b 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -39,7 +39,6 @@ #endif #endif -#include "common/cmake_defs.h" #include "defs_nr_common.h" #include "CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "PHY/defs_nr_sl_UE.h" diff --git a/radio/fhi_72/oran_isolate.h b/radio/fhi_72/oran_isolate.h index 21c63b0b48..7bc6430cd6 100644 --- a/radio/fhi_72/oran_isolate.h +++ b/radio/fhi_72/oran_isolate.h @@ -27,7 +27,6 @@ #include #include -#include "common/cmake_defs.h" #include "xran_fh_o_du.h" #include "openair1/PHY/impl_defs_nr.h" #include "openair1/PHY/TOOLS/tools_defs.h" From e3ac95035fa2d1a091bf2f944006bad27635db44 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 18 Mar 2026 14:26:47 +0100 Subject: [PATCH 30/33] Remove unused ci-scripts/mysql4testresults/ dir and content --- .../mysql4testresults/docker-compose.yml | 12 ------- ci-scripts/mysql4testresults/sql_connect.py | 33 ------------------- 2 files changed, 45 deletions(-) delete mode 100644 ci-scripts/mysql4testresults/docker-compose.yml delete mode 100644 ci-scripts/mysql4testresults/sql_connect.py diff --git a/ci-scripts/mysql4testresults/docker-compose.yml b/ci-scripts/mysql4testresults/docker-compose.yml deleted file mode 100644 index 1c60057ab2..0000000000 --- a/ci-scripts/mysql4testresults/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: '2' -services: - mysql: - container_name: oaicicd_mysql - restart: always - image: mysql:latest - environment: - MYSQL_ROOT_PASSWORD: 'ucZBc2XRYdvEm59F' - ports: - - "3307:3306" - volumes: - - /home/oaicicd/mysql/data:/var/lib/mysql diff --git a/ci-scripts/mysql4testresults/sql_connect.py b/ci-scripts/mysql4testresults/sql_connect.py deleted file mode 100644 index 333e573e78..0000000000 --- a/ci-scripts/mysql4testresults/sql_connect.py +++ /dev/null @@ -1,33 +0,0 @@ -import pymysql -import sys -from datetime import datetime - -#This is the script used to write the test results to the mysql DB -#Called by Jenkins pipeline (jenkinsfile) -#Must be located in /home/oaicicid/mysql on the database host -#Usage from Jenkinsfile : -#python3 /home/oaicicd/mysql/sql_connect.py ${JOB_NAME} ${params.eNB_MR} ${params.eNB_Branch} ${env.BUILD_ID} ${env.BUILD_URL} ${StatusForDb} '' - -class SQLConnect: - def __init__(self): - self.connection = pymysql.connect( - host='172.22.0.2', - user='root', - password = 'ucZBc2XRYdvEm59F', - db='oaicicd_tests', - port=3306 - ) - - def put(self,TEST,MR,BRANCH,BUILD,BUILD_LINK,STATUS): - now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - cur=self.connection.cursor() - cur.execute ('INSERT INTO test_results (TEST,MR,BRANCH,BUILD,BUILD_LINK,STATUS,DATE) VALUES (%s,%s,%s,%s,%s,%s,%s);' , (TEST, MR, BRANCH, BUILD, BUILD_LINK, STATUS, now)) - self.connection.commit() - self.connection.close() - - -if __name__ == "__main__": - mydb=SQLConnect() - mydb.put(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4],sys.argv[5],sys.argv[6]) - - From 0db8ddac08cc29f5cd9e9e917bd4432f180028a1 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 22 Oct 2025 17:30:50 +0100 Subject: [PATCH 31/33] Implementing delay compensation during SRS-based channel estimation --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 89 +++++++++++++++---- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 3 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 3 +- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 45fe87e040..7c5accdb68 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -780,7 +780,8 @@ int nr_srs_channel_estimation(int ant, c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], uint32_t *signal_power, uint32_t *noise_power, - int16_t *noise_power_per_rb) + int16_t *noise_power_per_rb, + c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]) { #ifdef SRS_DEBUG LOG_I(NR_PHY, "Calling %s function\n", __FUNCTION__); @@ -797,40 +798,29 @@ int nr_srs_channel_estimation(int ant, if (N_ap == 4 && ((K_TC == 2 && srs_pdu->cyclic_shift >= 4) || (K_TC == 4 && srs_pdu->cyclic_shift >= 6))) { fd_cdm = 2; } - uint16_t subcarrier; c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS]; c16_t srs_estimated_channel_freq_avg[ofdm_symbol_size]; memset(srs_ls_estimated_channel, 0, ofdm_symbol_size * N_symb_SRS * sizeof(c16_t)); memset(srs_estimated_channel_freq_avg, 0, ofdm_symbol_size * sizeof(c16_t)); + delay_t delay = {0}; for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) { uint16_t srs_symbol_offset = srs_symb * ofdm_symbol_size; - // Additional 4 in the array size is needed to maintain 16 byte memory alignment required for AVX2 instructions in channel - // interpolation - c16_t srs_est[ofdm_symbol_size + 4] __attribute__((aligned(32))); - memset(srs_est, 0, (ofdm_symbol_size + 4) * sizeof(c16_t)); - - // Estimate 16 byte memory alignment offset for the first SRS subcarrier to use AVX2 instructions in channel interpolation - uint8_t mem_offset = (16 - (((intptr_t)&srs_est[first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]]) & 0xF)) - >> 2; // >> 2 <=> /sizeof(int32_t) - - c16_t ls_estimated = {0}; - #ifdef SRS_DEBUG LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant); LOG_I(NR_PHY, "============================== SRS symbol index %d ===========================\n", srs_symb); #endif - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]; + // Channel estimation based on least square method + + uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]; if (subcarrier >= ofdm_symbol_size) { subcarrier -= ofdm_symbol_size; } - uint16_t subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; - c16_t *srs_estimated_channel16 = &srs_est[subcarrier_abs]; - + c16_t ls_estimated = {0}; for (int k = 0; k < M_sc_b_SRS; k++) { if (k % fd_cdm == 0) { ls_estimated = (c16_t){0, 0}; @@ -852,7 +842,9 @@ int nr_srs_channel_estimation(int ant, } } - srs_ls_estimated_channel[srs_symbol_offset + subcarrier] = ls_estimated; + for (int ktc = 0; ktc < K_TC && srs_symbol_offset + subcarrier + ktc < ofdm_symbol_size * N_symb_SRS; ktc++) { + srs_ls_estimated_channel[srs_symbol_offset + subcarrier + ktc] = ls_estimated; + } #ifdef SRS_DEBUG int subcarrier_log = subcarrier - subcarrier_offset; @@ -874,6 +866,44 @@ int nr_srs_channel_estimation(int ant, ls_estimated.i); #endif + // Subcarrier increment + subcarrier += K_TC; + if (subcarrier >= ofdm_symbol_size) { + subcarrier -= ofdm_symbol_size; + } + } // for (int k = 0; k < M_sc_b_SRS; k++) + + // Delay estimation + c16_t ch_estimates_time[ofdm_symbol_size] __attribute__((aligned(32))); + nr_est_delay(ofdm_symbol_size, srs_ls_estimated_channel, ch_estimates_time, &delay); + + // Interpolation of LS estimates + + // Additional 4 in the array size is needed to maintain 16 byte memory alignment required for AVX2 instructions in channel + // interpolation + c16_t srs_est[ofdm_symbol_size + 4] __attribute__((aligned(32))); + memset(srs_est, 0, (ofdm_symbol_size + 4) * sizeof(c16_t)); + + // Estimate 16 byte memory alignment offset for the first SRS subcarrier to use AVX2 instructions in channel interpolation + uint8_t mem_offset = + (16 - (((intptr_t)&srs_est[first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]]) & 0xF)) / sizeof(c16_t); + + uint16_t subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; + c16_t *srs_estimated_channel16 = &srs_est[subcarrier_abs]; + + subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]; + if (subcarrier >= ofdm_symbol_size) { + subcarrier -= ofdm_symbol_size; + } + + int delay_idx = get_delay_idx(delay.est_delay, MAX_DELAY_COMP); + const c16_t *srs_delay_table = delay_table[delay_idx]; + + for (int k = 0; k < M_sc_b_SRS; k++) { + + // Apply delay + ls_estimated = c16mulShift(srs_ls_estimated_channel[srs_symbol_offset + subcarrier], srs_delay_table[subcarrier], 8); + // Channel interpolation if (srs_pdu->comb_size == 0) { if (k == 0) { // First subcarrier case @@ -914,6 +944,27 @@ int nr_srs_channel_estimation(int ant, } // for (int k = 0; k < M_sc_b_SRS; k++) + // Revert delay + int inv_delay_idx = get_delay_idx(-delay.est_delay, MAX_DELAY_COMP); + const c16_t *srs_inv_delay_table = delay_table[inv_delay_idx]; + subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; + subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; + if (subcarrier >= ofdm_symbol_size) { + subcarrier -= ofdm_symbol_size; + } + for (int k = 0; k < K_TC * M_sc_b_SRS; k++) { + srs_est[subcarrier_abs] = c16mulShift(srs_est[subcarrier_abs], srs_inv_delay_table[subcarrier], 8); + // Subcarrier increment + subcarrier++; + if (subcarrier >= ofdm_symbol_size) { + subcarrier -= ofdm_symbol_size; + } + subcarrier_abs++; + if (subcarrier_abs >= ofdm_symbol_size) { + subcarrier_abs -= ofdm_symbol_size; + } + } + memcpy(&srs_estimated_channel_freq[srs_symbol_offset], &srs_est[mem_offset], ofdm_symbol_size * sizeof(c16_t)); // Average srs channel estimates over multiple symbols @@ -996,7 +1047,7 @@ int nr_srs_channel_estimation(int ant, return -1; } - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; + uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; if (subcarrier >= ofdm_symbol_size) { subcarrier -= ofdm_symbol_size; } diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 21ecb39427..4530493d53 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -90,7 +90,8 @@ int nr_srs_channel_estimation(int ant, c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], uint32_t *signal_power, uint32_t *noise_power, - int16_t *noise_power_per_rb); + int16_t *noise_power_per_rb, + c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]); void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, c16_t *rxdataF_comp, diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 97ad60cfff..4dea08ea0f 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -905,7 +905,8 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, srs_estimated_channel_time_shifted[ant_rx_ind][p_ind], &signal_power, &noise_power, - noise_power_per_rb); + noise_power_per_rb, + frame_parms->delay_table); signal_power_avg += signal_power; From 4f31a4eb89fb491f23bfe6d0fdb500c79f6d6397 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 14 Jan 2026 14:41:41 +0000 Subject: [PATCH 32/33] The nr_srs_channel_estimation function is split into the nr_srs_ls_channel_estimation and nr_srs_channel_interpolation functions to allow the use of a common delay Define CIRCULAR_INC --- common/utils/T/tracer/gnb.c | 2 +- common/utils/nr/nr_common.h | 4 + .../NR_ESTIMATION/nr_ul_channel_estimation.c | 259 +++++++++--------- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 54 ++-- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 84 ++++-- 5 files changed, 231 insertions(+), 172 deletions(-) diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c index d47f627341..ebed555ae6 100644 --- a/common/utils/T/tracer/gnb.c +++ b/common/utils/T/tracer/gnb.c @@ -195,7 +195,7 @@ static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, g e->ul_freq_estimate_ue_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 2048, -10, 80); - l = new_framelog(h, database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", "subframe", "chest_t"); + l = new_framelog(h, database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", "subframe", "chest_f"); framelog_set_update_only_at_sf9(l, 0); v = new_view_xy(2048, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE); logger_add_view(l, v); diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 2197fe91a7..0b54bd233f 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -366,6 +366,10 @@ void nr_deconstruct_5g_s_tmsi(const uint64_t fiveg_s_tmsi, uint16_t *amf_set_id, #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) #define BOUNDED_EVAL(a, b, c) (min(c, max(a, b))) +/* Macro used to perform a circular increment. This implementation is computationally more efficient than using the remainder of the + * integer division, and improves code readability when compared to repetitive if... else statements. */ +#define CIRCULAR_INC(val, inc, size) (((val) + (inc) >= (size)) ? ((val) + (inc) - (size)) : ((val) + (inc))) + static const char *const duplex_mode_txt[] = {"FDD", "TDD"}; #ifdef __cplusplus diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 7c5accdb68..d51eb1919c 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -765,30 +765,23 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, } // Antenna loop } -int nr_srs_channel_estimation(int ant, - int p_index, - uint16_t ofdm_symbol_size, - uint16_t first_carrier_offset, - uint8_t N_symb_SRS, - const nfapi_nr_srs_pdu_t *srs_pdu, - const nr_srs_info_t *nr_srs_info, - const c16_t *srs_generated_signal, - c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], - c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], - c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], - c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], - c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], - uint32_t *signal_power, - uint32_t *noise_power, - int16_t *noise_power_per_rb, - c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]) +int nr_srs_ls_channel_estimation(int ant, + int p_index, + uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const c16_t *srs_generated_signal, + c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], + c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS], + delay_t *delay) { #ifdef SRS_DEBUG LOG_I(NR_PHY, "Calling %s function\n", __FUNCTION__); #endif const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB; - const uint64_t first_subcarrier = (first_carrier_offset - (ofdm_symbol_size >> 1)) + srs_pdu->bwp_start * NR_NB_SC_PER_RB; const uint8_t N_ap = 1 << srs_pdu->num_ant_ports; const uint8_t K_TC = 2 << srs_pdu->comb_size; @@ -799,11 +792,7 @@ int nr_srs_channel_estimation(int ant, fd_cdm = 2; } - c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS]; - c16_t srs_estimated_channel_freq_avg[ofdm_symbol_size]; memset(srs_ls_estimated_channel, 0, ofdm_symbol_size * N_symb_SRS * sizeof(c16_t)); - memset(srs_estimated_channel_freq_avg, 0, ofdm_symbol_size * sizeof(c16_t)); - delay_t delay = {0}; for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) { uint16_t srs_symbol_offset = srs_symb * ofdm_symbol_size; @@ -813,12 +802,7 @@ int nr_srs_channel_estimation(int ant, LOG_I(NR_PHY, "============================== SRS symbol index %d ===========================\n", srs_symb); #endif - // Channel estimation based on least square method - - uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } + uint16_t subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb], 0, ofdm_symbol_size); c16_t ls_estimated = {0}; for (int k = 0; k < M_sc_b_SRS; k++) { @@ -835,10 +819,7 @@ int nr_srs_channel_estimation(int ant, ls_estimated = c16maddConjShift(generated_srs, received_srs, ls_estimated, nr_srs_info->srs_generated_signal_bits); // Subcarrier increment - subcarrier_cdm += K_TC; - if (subcarrier_cdm >= ofdm_symbol_size) { - subcarrier_cdm = subcarrier_cdm - ofdm_symbol_size; - } + subcarrier_cdm = CIRCULAR_INC(subcarrier_cdm, K_TC, ofdm_symbol_size); } } @@ -867,17 +848,116 @@ int nr_srs_channel_estimation(int ant, #endif // Subcarrier increment - subcarrier += K_TC; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } + subcarrier = CIRCULAR_INC(subcarrier, K_TC, ofdm_symbol_size); } // for (int k = 0; k < M_sc_b_SRS; k++) // Delay estimation - c16_t ch_estimates_time[ofdm_symbol_size] __attribute__((aligned(32))); - nr_est_delay(ofdm_symbol_size, srs_ls_estimated_channel, ch_estimates_time, &delay); + if (srs_symb == 0) { + c16_t ch_estimates_time[ofdm_symbol_size] __attribute__((aligned(32))); + nr_est_delay(ofdm_symbol_size, srs_ls_estimated_channel, ch_estimates_time, delay); + } + } // for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) - // Interpolation of LS estimates + return 0; +} + +void nr_srs_noise_power_estimation(uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + uint32_t signal_power, + const c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], + uint32_t *noise_power, + int16_t *noise_power_per_rb) +{ + const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB; + const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index); + int tot_subcarriers = m_SRS_b * NR_NB_SC_PER_RB; + + uint16_t subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[0][0], 0, ofdm_symbol_size); + + if (subcarrier + tot_subcarriers < ofdm_symbol_size) { + *noise_power = signal_energy_nodc(&srs_received_noise[subcarrier], tot_subcarriers) / tot_subcarriers; + } else { + int size1 = ofdm_symbol_size - subcarrier; + int size2 = tot_subcarriers - size1; + uint64_t noise_power_p1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1; + uint64_t noise_power_p2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2; + *noise_power = (noise_power_p1 + noise_power_p2) / tot_subcarriers; + } + + // Compute SNR per RB on symbol 0 + subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[0][0], 0, ofdm_symbol_size); + for (int rb = 0; rb < m_SRS_b; rb++) { + if (subcarrier + NR_NB_SC_PER_RB < ofdm_symbol_size) { + noise_power_per_rb[rb] += signal_energy_nodc(&srs_received_noise[subcarrier], NR_NB_SC_PER_RB); + } else { + int size1 = ofdm_symbol_size - subcarrier; + int size2 = NR_NB_SC_PER_RB - size1; + uint32_t noise_power_per_rb1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1; + uint32_t noise_power_per_rb2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2; + noise_power_per_rb[rb] += (noise_power_per_rb1 + noise_power_per_rb2) / NR_NB_SC_PER_RB; + } + noise_power_per_rb[rb] = max(noise_power_per_rb[rb], 1); + subcarrier = CIRCULAR_INC(subcarrier, NR_NB_SC_PER_RB, ofdm_symbol_size); + +#ifdef SRS_DEBUG + LOG_I(NR_PHY, + "[RB %3i] noise_power_per_rb = %i, SNR_per_rb = %i dB\n", + rb, + noise_power_per_rb[rb], + dB_fixed(signal_power) - dB_fixed(noise_power_per_rb[rb])); +#endif + } + +#ifdef SRS_DEBUG + int32_t signal_power_dB = dB_fixed(signal_power); + int32_t noise_power_dB = dB_fixed(*noise_power); + LOG_I(NR_PHY, + "signal_power = %i dB, noise_power = %i dB, SNR = %i dB\n", + signal_power_dB, + noise_power_dB, + signal_power_dB - noise_power_dB); +#endif +} + +int nr_srs_channel_interpolation(int ant, + int p_index, + uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS], + int est_delay, + c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], + c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], + c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], + c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], + uint32_t *signal_power, + c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]) +{ +#ifdef SRS_DEBUG + LOG_I(NR_PHY, "Calling %s function\n", __FUNCTION__); +#endif + + const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB; + const uint64_t first_subcarrier = (first_carrier_offset - (ofdm_symbol_size >> 1)) + srs_pdu->bwp_start * NR_NB_SC_PER_RB; + const uint8_t K_TC = 2 << srs_pdu->comb_size; + const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index); + const uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB / K_TC; + + c16_t srs_estimated_channel_freq_avg[ofdm_symbol_size]; + memset(srs_estimated_channel_freq_avg, 0, ofdm_symbol_size * sizeof(c16_t)); + + for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) { + uint16_t srs_symbol_offset = srs_symb * ofdm_symbol_size; + +#ifdef SRS_DEBUG + LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant); + LOG_I(NR_PHY, "============================== SRS symbol index %d ===========================\n", srs_symb); +#endif // Additional 4 in the array size is needed to maintain 16 byte memory alignment required for AVX2 instructions in channel // interpolation @@ -891,18 +971,15 @@ int nr_srs_channel_estimation(int ant, uint16_t subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; c16_t *srs_estimated_channel16 = &srs_est[subcarrier_abs]; - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } + uint16_t subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb], 0, ofdm_symbol_size); - int delay_idx = get_delay_idx(delay.est_delay, MAX_DELAY_COMP); + int delay_idx = get_delay_idx(est_delay, MAX_DELAY_COMP); const c16_t *srs_delay_table = delay_table[delay_idx]; for (int k = 0; k < M_sc_b_SRS; k++) { // Apply delay - ls_estimated = c16mulShift(srs_ls_estimated_channel[srs_symbol_offset + subcarrier], srs_delay_table[subcarrier], 8); + c16_t ls_estimated = c16mulShift(srs_ls_estimated_channel[srs_symbol_offset + subcarrier], srs_delay_table[subcarrier], 8); // Channel interpolation if (srs_pdu->comb_size == 0) { @@ -935,34 +1012,21 @@ int nr_srs_channel_estimation(int ant, } // Subcarrier increment - subcarrier += K_TC; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } - + subcarrier = CIRCULAR_INC(subcarrier, K_TC, ofdm_symbol_size); subcarrier_abs += K_TC; - } // for (int k = 0; k < M_sc_b_SRS; k++) // Revert delay - int inv_delay_idx = get_delay_idx(-delay.est_delay, MAX_DELAY_COMP); + int inv_delay_idx = get_delay_idx(-est_delay, MAX_DELAY_COMP); const c16_t *srs_inv_delay_table = delay_table[inv_delay_idx]; - subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } + subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; + subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][0], 0, ofdm_symbol_size); + for (int k = 0; k < K_TC * M_sc_b_SRS; k++) { srs_est[subcarrier_abs] = c16mulShift(srs_est[subcarrier_abs], srs_inv_delay_table[subcarrier], 8); // Subcarrier increment - subcarrier++; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } + subcarrier = CIRCULAR_INC(subcarrier, 1, ofdm_symbol_size); subcarrier_abs++; - if (subcarrier_abs >= ofdm_symbol_size) { - subcarrier_abs -= ofdm_symbol_size; - } } memcpy(&srs_estimated_channel_freq[srs_symbol_offset], &srs_est[mem_offset], ofdm_symbol_size * sizeof(c16_t)); @@ -975,11 +1039,7 @@ int nr_srs_channel_estimation(int ant, ofdm_symbol_size); #ifdef SRS_DEBUG - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } - + subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb], 0, ofdm_symbol_size); subcarrier_abs = first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; for (int k = 0; k < K_TC * M_sc_b_SRS; k++) { @@ -1007,10 +1067,7 @@ int nr_srs_channel_estimation(int ant, srs_received_noise[srs_symbol_offset + subcarrier].i); // Subcarrier increment - subcarrier++; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } + subcarrier = CIRCULAR_INC(subcarrier, 1, ofdm_symbol_size); subcarrier_abs++; } #endif @@ -1047,61 +1104,5 @@ int nr_srs_channel_estimation(int ant, return -1; } - uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } - - if (p_index == 0) { - if (subcarrier + tot_subcarriers < ofdm_symbol_size) { - *noise_power = signal_energy_nodc(&srs_received_noise[subcarrier], tot_subcarriers) / tot_subcarriers; - } else { - int size1 = ofdm_symbol_size - subcarrier; - int size2 = tot_subcarriers - size1; - uint64_t noise_power_p1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1; - uint64_t noise_power_p2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2; - *noise_power = (noise_power_p1 + noise_power_p2) / tot_subcarriers; - } - } - - // Compute SNR per RB for port 0 and symbol 0 - if (p_index == 0) { - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; - for (int rb = 0; rb < m_SRS_b; rb++) { - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } - if (subcarrier + NR_NB_SC_PER_RB < ofdm_symbol_size) { - noise_power_per_rb[rb] += signal_energy_nodc(&srs_received_noise[subcarrier], NR_NB_SC_PER_RB); - } else { - int size1 = ofdm_symbol_size - subcarrier; - int size2 = NR_NB_SC_PER_RB - size1; - uint32_t noise_power_per_rb1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1; - uint32_t noise_power_per_rb2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2; - noise_power_per_rb[rb] += (noise_power_per_rb1 + noise_power_per_rb2) / NR_NB_SC_PER_RB; - } - noise_power_per_rb[rb] = max(noise_power_per_rb[rb], 1); - subcarrier += NR_NB_SC_PER_RB; - -#ifdef SRS_DEBUG - LOG_I(NR_PHY, - "[RB %3i] noise_power_per_rb = %i, SNR_per_rb = %i dB\n", - rb, - noise_power_per_rb[rb], - dB_fixed(*signal_power) - dB_fixed(noise_power_per_rb[rb])); -#endif - } - } - -#ifdef SRS_DEBUG - int32_t signal_power_dB = dB_fixed(*signal_power); - int32_t noise_power_dB = dB_fixed(*noise_power); - LOG_I(NR_PHY, - "signal_power = %i dB, noise_power = %i dB, SNR = %i dB\n", - signal_power_dB, - noise_power_dB, - signal_power_dB - noise_power_dB); -#endif - return 0; } diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 4530493d53..533c755241 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -75,23 +75,43 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, unsigned char symbol, uint32_t nb_re_pusch); -int nr_srs_channel_estimation(int ant, - int p_index, - uint16_t ofdm_symbol_size, - uint16_t first_carrier_offset, - uint8_t N_symb_SRS, - const nfapi_nr_srs_pdu_t *srs_pdu, - const nr_srs_info_t *nr_srs_info, - const c16_t *srs_generated_signal, - c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], - c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], - c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], - c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], - c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], - uint32_t *signal_power, - uint32_t *noise_power, - int16_t *noise_power_per_rb, - c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]); +int nr_srs_ls_channel_estimation(int ant, + int p_index, + uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const c16_t *srs_generated_signal, + c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], + c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS], + delay_t *delay); + +int nr_srs_channel_interpolation(int ant, + int p_index, + uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS], + int est_delay, + c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], + c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], + c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], + c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], + uint32_t *signal_power, + c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]); + +void nr_srs_noise_power_estimation(uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + uint32_t signal_power, + const c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], + uint32_t *noise_power, + int16_t *noise_power_per_rb); void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, c16_t *rxdataF_comp, diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 4dea08ea0f..b6b29f20d3 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -880,33 +880,49 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, stop_meas(&gNB->get_srs_signal_stats); uint32_t signal_power_avg = 0; - uint32_t noise_power_avg = 0; - int16_t noise_power_per_rb[srs_pdu->bwp_size]; - memset(noise_power_per_rb, 0, srs_pdu->bwp_size * sizeof(int16_t)); + c16_t srs_ls_estimated_channel[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS]; if (*srs_est >= 0) { start_meas(&gNB->srs_channel_estimation_stats); + + delay_t delay = {0}; + for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) { + for (int p_ind = 0; p_ind < N_ap; p_ind++) { + delay_t delay_aux = {0}; + nr_srs_ls_channel_estimation(ant_rx_ind, + p_ind, + ofdm_symbol_size, + frame_parms->first_carrier_offset, + N_symb_SRS, + srs_pdu, + nr_srs_info, + nr_srs_info->srs_generated_signal[p_ind], + srs_received_signal[ant_rx_ind], + srs_ls_estimated_channel[ant_rx_ind][p_ind], + &delay_aux); + if (delay_aux.delay_max_val > delay.delay_max_val) + delay = delay_aux; + } + } + for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) { - uint32_t noise_power = 0; for (int p_ind = 0; p_ind < N_ap; p_ind++) { uint32_t signal_power = 0; - nr_srs_channel_estimation(ant_rx_ind, - p_ind, - ofdm_symbol_size, - frame_parms->first_carrier_offset, - N_symb_SRS, - srs_pdu, - nr_srs_info, - nr_srs_info->srs_generated_signal[p_ind], - srs_received_signal[ant_rx_ind], - srs_received_noise[ant_rx_ind], - srs_estimated_channel_freq[ant_rx_ind][p_ind], - srs_estimated_channel_time[ant_rx_ind][p_ind], - srs_estimated_channel_time_shifted[ant_rx_ind][p_ind], - &signal_power, - &noise_power, - noise_power_per_rb, - frame_parms->delay_table); + nr_srs_channel_interpolation(ant_rx_ind, + p_ind, + ofdm_symbol_size, + frame_parms->first_carrier_offset, + N_symb_SRS, + srs_pdu, + nr_srs_info, + srs_ls_estimated_channel[ant_rx_ind][p_ind], + delay.est_delay, + srs_received_noise[ant_rx_ind], + srs_estimated_channel_freq[ant_rx_ind][p_ind], + srs_estimated_channel_time[ant_rx_ind][p_ind], + srs_estimated_channel_time_shifted[ant_rx_ind][p_ind], + &signal_power, + frame_parms->delay_table); signal_power_avg += signal_power; @@ -914,7 +930,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, T_INT(gNB->Mod_id), T_INT(srs_pdu->rnti), T_INT(frame_rx), - T_INT(slot_rx), + T_INT(0), T_INT(ant_rx_ind), T_INT(p_ind), T_BUFFER(srs_estimated_channel_freq[ant_rx_ind][p_ind], N_symb_SRS * ofdm_symbol_size * sizeof(c16_t))); @@ -923,17 +939,35 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, T_INT(gNB->Mod_id), T_INT(srs_pdu->rnti), T_INT(frame_rx), - T_INT(slot_rx), + T_INT(0), T_INT(ant_rx_ind), T_INT(p_ind), T_BUFFER(srs_estimated_channel_time_shifted[ant_rx_ind][p_ind], NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size * sizeof(c16_t))); } - noise_power_avg += noise_power; } + signal_power_avg /= (nb_antennas_rx * N_ap); - noise_power_avg /= nb_antennas_rx; signal_power_avg = max(signal_power_avg, 1); + + uint32_t noise_power_avg = 0; + int16_t noise_power_per_rb[srs_pdu->bwp_size]; + memset(noise_power_per_rb, 0, srs_pdu->bwp_size * sizeof(int16_t)); + for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) { + uint32_t noise_power_per_ant = 0; + nr_srs_noise_power_estimation(ofdm_symbol_size, + frame_parms->first_carrier_offset, + N_symb_SRS, + srs_pdu, + nr_srs_info, + signal_power_avg, + srs_received_noise[ant_rx_ind], + &noise_power_per_ant, + noise_power_per_rb); + noise_power_avg += noise_power_per_ant; + } + + noise_power_avg /= nb_antennas_rx; gNB->srs->snr = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_avg, 1)); const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index); From b9803d63664c37d78fba7343e5f6378dbd705f75 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 19 Mar 2026 22:01:23 +0100 Subject: [PATCH 33/33] doc: Add description of ssPBCH_BlockPower into ORAN documentation --- doc/ORAN_FHI7.2_Tutorial.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index a241fbb3f5..8296d9371a 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -980,6 +980,14 @@ Edit the sample OAI gNB configuration file and check following parameters: * `GNB_IPV4_ADDRESS_FOR_NGU` shall match your gNB N3 interface IP address * `prach_ConfigurationIndex` * `prach_msg1_FrequencyStart` + * `ssPBCH_BlockPower` is average EPRE of the resource elements carrying the secondary synchronization signals, expressed in dBm. It can be estimated using the following formula: + + > ssPBCH_BlockPower = P_TX − 10 x log10(N_RE) + 10 x log10(N_antenna_SSB) + + where: + * `P_TX` is the total transmit power of the RU in dBm (configured on the RU). + * `N_RE` is the number of resource elements used for the transmission. + * `N_antenna_SSB` is the number of antenna ports used for SSB transmission (currently, a single antenna port is used for SSB transmission). * Adjust the frequency, bandwidth and SSB position * `L1s` section