From 80fb09ba218a46de08f5463886795b6cd1f66e0c Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Tue, 3 Mar 2026 08:22:38 +0100 Subject: [PATCH 01/30] Build BladeRF strictly from source. To avoid version mismatch between built Docker image and BladeRF FW. --- cmake_targets/tools/build_helper | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 64c171276c..298977d7e9 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -338,7 +338,7 @@ install_bladerf_driver_from_source(){ rm -rf /tmp/bladeRF git clone https://github.com/Nuand/bladeRF.git cd bladeRF - git checkout tags/2016.06 + git checkout tags/2025.10 mkdir -p build cd build $CMAKE ../ @@ -350,14 +350,12 @@ install_bladerf_driver_from_source(){ check_install_bladerf_driver(){ if [[ "$OS_BASEDISTRO" == "debian" ]]; then - $SUDO apt-get install -y bladerf libbladerf-dev - $SUDO apt-get install -y bladerf-firmware-fx3 - $SUDO apt-get install -y bladerf-fpga-hostedx40 - elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then - install_bladerf_driver_from_source - else - echo_error "BladeRF Installer for OAI does not support automatic build. Install BladeRF compiling sources manually from BladeRF website" - fi + $SUDO apt-get update + $SUDO apt-get install -y libcurl4-openssl-dev + elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then + $SUDO dnf -y install libcurl-devel + fi + install_bladerf_driver_from_source } check_install_lmssdr_driver(){ @@ -371,8 +369,6 @@ check_install_lmssdr_driver(){ echo_info "https://wiki.myriadrf.org/Lime_Suite" echo_fatal "Cannot compile lmssdr device" fi - - } install_soapy_from_source(){ From 94a857352170eb49bb71c7e4c2db934b26603299 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 6 Mar 2026 11:14:09 +0100 Subject: [PATCH 02/30] limit dl_DataToUL_ACK values to 15 as per standard to prevent ASN1 encoding/decoding failure when min feedback time is too high --- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 054703c2e2..75ac4bb061 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1207,10 +1207,16 @@ static void set_dl_DataToUL_ACK(NR_PUCCH_Config_t *pucch_Config, int min_feedbac long *delay[8]; for (int i = 0; i < 8; i++) { int curr_delay = i + min_feedback_time; + // dl-DataToUL-ACK SEQUENCE (SIZE (1..8)) OF INTEGER (0..15) + if (curr_delay > 15) + break; delay[i] = calloc(1,sizeof(*delay[i])); *delay[i] = curr_delay; asn1cSeqAdd(&pucch_Config->dl_DataToUL_ACK->list,delay[i]); } + AssertFatal(pucch_Config->dl_DataToUL_ACK->list.count > 0, + "Minimum feedback time too high %d, cannot set any dl_DataToUL_ACK value\n", + min_feedback_time); } // PUCCH resource set 0 for configuration with O_uci <= 2 bits and/or a positive or negative SR (section 9.2.1 of 38.213) From 803d87ef549d8ef63be95fbd62ba2589b9f7f126 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Mar 2026 13:58:50 +0100 Subject: [PATCH 03/30] harmonize the use of definition for number of symbols per slot (no need to have two of them) --- common/utils/nr/nr_common.h | 4 +- executables/nr-ru.c | 2 +- executables/nr-ue.c | 2 +- openair1/PHY/INIT/nr_init.c | 4 +- openair1/PHY/MODULATION/modulation_common.h | 2 +- openair1/PHY/MODULATION/nr_modulation.h | 2 +- openair1/PHY/MODULATION/ofdm_mod.c | 2 +- openair1/PHY/MODULATION/slot_fep_nr.c | 2 +- openair1/PHY/NR_TRANSPORT/nr_prach.c | 2 +- openair1/PHY/NR_TRANSPORT/nr_ulsch.c | 2 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 4 +- openair1/PHY/NR_TRANSPORT/srs_rx.c | 2 +- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 6 +-- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 20 +++++----- openair1/PHY/defs_nr_common.h | 2 - openair1/SCHED_NR/nr_ru_procedures.c | 2 +- openair1/SCHED_NR/phy_frame_config_nr.c | 37 +++++++++---------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 4 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 10 ++--- .../SCHED_NR_UE/phy_procedures_nr_ue_sl.c | 2 +- openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 2 +- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/srssim.c | 2 +- openair2/LAYER2/NR_MAC_UE/config_ue.c | 10 ++--- openair2/LAYER2/NR_MAC_UE/config_ue_sl.c | 10 ++--- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 4 +- .../LAYER2/NR_MAC_UE/nr_ue_scheduler_sl.c | 8 ++-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 2 +- openair2/RRC/NR_UE/verify_RRC.c | 4 +- 33 files changed, 81 insertions(+), 84 deletions(-) diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 58dad544cc..3da8b7ece3 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -84,8 +84,8 @@ static inline const char *rnti_types(nr_rnti_type_t rr) #define MU_SCS(m) (15 << m) #define MAX_GSCN_BAND 620 // n78 has the highest GSCN range of 619 -#define NR_NUMBER_OF_SYMBOLS_PER_SLOT 14 -#define NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP 12 +#define NR_SYMBOLS_PER_SLOT 14 +#define NR_SYMBOLS_PER_SLOT_EXTENDED_CP 12 #define NR_MAX_NB_LAYERS 4 // 8 #define NR_MAX_CSI_PORTS 12 diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 7c5a87a0b0..2f5f136d17 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -538,7 +538,7 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp) if(slot_type == NR_MIXED_SLOT) { int txsymb = 0; - for(int symbol_count = 0; symbol_counttdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) txsymb++; } diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 75814596d3..f52f418732 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -281,7 +281,7 @@ static int nr_ue_slot_select(const fapi_nr_config_request_t *cfg, int nr_slot) if (current_slot->max_num_of_symbol_per_slot_list[0].slot_config == 2) return NR_MIXED_SLOT; - for (int i = 1; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT; i++) { + for (int i = 1; i < NR_SYMBOLS_PER_SLOT; i++) { // if the 1st symbol is DL and any other is not, the slot is mixed if (current_slot->max_num_of_symbol_per_slot_list[i].slot_config != 0) { return NR_MIXED_SLOT; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index d8b34b2598..e140b9dab0 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -435,8 +435,8 @@ void init_nr_transport(PHY_VARS_gNB *gNB) fp->slots_per_frame; int nb_ul_slots_period = 0; if (cfg->cell_config.frame_duplex_type.value) { - for(int i=0; itdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[j].slot_config.value == 1) { // UL symbol nb_ul_slots_period++; break; diff --git a/openair1/PHY/MODULATION/modulation_common.h b/openair1/PHY/MODULATION/modulation_common.h index 2973c36257..3e418594bc 100644 --- a/openair1/PHY/MODULATION/modulation_common.h +++ b/openair1/PHY/MODULATION/modulation_common.h @@ -53,7 +53,7 @@ void nr_normal_prefix_mod(c16_t *txdataF, uint8_t nsymb, const NR_DL_FRAME_PARMS *frame_parms, uint32_t slot, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_slot, LTE_DL_FRAME_PARMS *frame_parms); diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 9e8ac3ba3c..52a64fc161 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -118,7 +118,7 @@ void nr_ofdm_demod_and_rx_rotation(c16_t **rxdata, int slot, int slot_offsetF, enum nr_Link linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); void perform_symbol_rotation(NR_DL_FRAME_PARMS *fp, double f0, c16_t *symbol_rotation); diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index c3311fb78a..23f7b296c8 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -72,7 +72,7 @@ void nr_normal_prefix_mod(c16_t *txdataF, uint8_t nsymb, const NR_DL_FRAME_PARMS *frame_parms, uint32_t slot, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { // This function works only slot wise. For more generic symbol generation refer nr_feptx0() if (frame_parms->numerology_index != 0) { // case where numerology != 0 diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 99cbf1c652..b690657ad5 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -227,7 +227,7 @@ void nr_ofdm_demod_and_rx_rotation(c16_t **rxdata, int slot, int slot_offsetF, enum nr_Link linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { for (int aa = 0; aa < nb_antennas; aa++) { for (uint8_t symbol = 0; symbol < fp->symbols_per_slot; symbol++) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index e42c02953c..5395c33df9 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -105,7 +105,7 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n fapi_beam_idx, &gNB->common_vars, Slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, + NR_SYMBOLS_PER_SLOT, bitmap); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index b963b7d970..72dccf4a40 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -160,7 +160,7 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t fapi_beam_idx, &gNB->common_vars, slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, + NR_SYMBOLS_PER_SLOT, bitmap); } ulsch->frame = frame; diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index aa3a6e5907..51cb354f98 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -73,7 +73,7 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t fapi_beam_idx, &gNB->common_vars, slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, + NR_SYMBOLS_PER_SLOT, bitmap); } memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); @@ -1069,7 +1069,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, // first compute DMRS component const int scramble = pucch_pdu->dmrs_scrambling_id * 2; uint32_t x2 = - ((1ULL << 17) * ((NR_NUMBER_OF_SYMBOLS_PER_SLOT * slot + pucch_pdu->start_symbol_index + symb + 1) * (scramble + 1)) + ((1ULL << 17) * ((NR_SYMBOLS_PER_SLOT * slot + pucch_pdu->start_symbol_index + symb + 1) * (scramble + 1)) + scramble) % (1U << 31); // c_init calculation according to TS38.211 subclause #ifdef DEBUG_NR_PUCCH_RX diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index 0637a8abce..05cddefd20 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -63,7 +63,7 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu fapi_beam_idx, &gNB->common_vars, slot, - NR_NUMBER_OF_SYMBOLS_PER_SLOT, + NR_SYMBOLS_PER_SLOT, bitmap); } memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t)); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 6872306dfe..d80a99bb73 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -162,7 +162,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const uint8_t slot, nr_phy_data_tx_t *phy_data, c16_t **txdataF, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); /** \brief This function does IFFT for PUSCH */ @@ -173,14 +173,14 @@ uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, c16_t **txdataF, c16_t **txdata, uint32_t linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT], + bool was_symbol_used[NR_SYMBOLS_PER_SLOT], bool no_phase_pre_comp); bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, c16_t **txdataF, nr_phy_data_tx_t *phy_data, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]); + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]); void clean_UE_harq(PHY_VARS_NR_UE *UE); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 881ce016bc..25b5766f07 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1027,11 +1027,11 @@ static uci_on_pusch_bit_type_t *nr_data_control_mapping(const nfapi_nr_ue_pusch_ if (!pusch_pdu || !codeword || codeword_len == 0 || !template) return NULL; const uint8_t n_symbols = pusch_pdu->nr_of_symbols; - if (n_symbols == 0 || n_symbols > NR_NUMBER_OF_SYMBOLS_PER_SLOT) + if (n_symbols == 0 || n_symbols > NR_SYMBOLS_PER_SLOT) return NULL; - uint32_t m_ulsch_initial[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; - uint32_t m_uci_current[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; // This holds RE counts, not bit counts + uint32_t m_ulsch_initial[NR_SYMBOLS_PER_SLOT] = {0}; + uint32_t m_uci_current[NR_SYMBOLS_PER_SLOT] = {0}; // This holds RE counts, not bit counts if (initialize_mapping_resources(pusch_pdu, m_ulsch_initial, m_uci_current) != 0) { LOG_E(PHY, "Failed to initialize mapping resources\n"); @@ -1048,8 +1048,8 @@ static uci_on_pusch_bit_type_t *nr_data_control_mapping(const nfapi_nr_ue_pusch_ memset(template, 0, codeword_len * sizeof(uci_on_pusch_bit_type_t)); - uint32_t positions_by_sym[NR_NUMBER_OF_SYMBOLS_PER_SLOT][MAX_UCI_CODED_BITS] = {0}; - uint32_t count_by_sym[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; + uint32_t positions_by_sym[NR_SYMBOLS_PER_SLOT][MAX_UCI_CODED_BITS] = {0}; + uint32_t count_by_sym[NR_SYMBOLS_PER_SLOT] = {0}; struct map_uci_common_arg map_arg = {.template = template, .n_symbols = pusch_pdu->nr_of_symbols, @@ -1094,7 +1094,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, const uint8_t slot, nr_phy_data_tx_t *phy_data, c16_t **txdataF, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { int harq_pid = phy_data->ulsch.pusch_pdu.pusch_data.harq_process_id; @@ -1609,13 +1609,13 @@ uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, c16_t **txdataF, c16_t **txdata, uint32_t linktype, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT], + bool was_symbol_used[NR_SYMBOLS_PER_SLOT], bool no_phase_pre_comp) { int N_RB = (linktype == link_type_sl) ? frame_parms->N_RB_SL : frame_parms->N_RB_UL; if (!no_phase_pre_comp) { - for (int i = 0; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT; i++) { + for (int i = 0; i < NR_SYMBOLS_PER_SLOT; i++) { if (was_symbol_used[i] == false) continue; for (int ap = 0; ap < n_antenna_ports; ap++) { @@ -1626,7 +1626,7 @@ uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, for (int ap = 0; ap < n_antenna_ports; ap++) { if (frame_parms->Ncp == 1) { // extended cyclic prefix - for (int i = 0; i < NR_NUMBER_OF_SYMBOLS_PER_SLOT_EXTENDED_CP; i++) { + for (int i = 0; i < NR_SYMBOLS_PER_SLOT_EXTENDED_CP; i++) { if (was_symbol_used[i] == false) { memset(&txdata[ap][(frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples) * i], 0, @@ -1641,7 +1641,7 @@ uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, CYCLIC_PREFIX); } } else { // normal cyclic prefix - nr_normal_prefix_mod(txdataF[ap], txdata[ap], NR_NUMBER_OF_SYMBOLS_PER_SLOT, frame_parms, slot, was_symbol_used); + nr_normal_prefix_mod(txdataF[ap], txdata[ap], NR_SYMBOLS_PER_SLOT, frame_parms, slot, was_symbol_used); } } diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 20fc744f57..4b6737a4ed 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -42,8 +42,6 @@ #define MAX_NUM_SUBCARRIER_SPACING 5 #define NR_MAX_OFDM_SYMBOL_SIZE 8192 -#define NR_SYMBOLS_PER_SLOT NR_NUMBER_OF_SYMBOLS_PER_SLOT - #define ONE_OVER_SQRT2_Q15 23170 #define NR_MOD_TABLE_SIZE_SHORT 686 diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index ca712bbaf9..e19b332c80 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -157,7 +157,7 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) if (nr_slot_select(cfg,frame_tx,slot) == NR_UPLINK_SLOT) return; - nr_feptx0(ru,slot,0,NR_NUMBER_OF_SYMBOLS_PER_SLOT,aa); + nr_feptx0(ru, slot, 0, NR_SYMBOLS_PER_SLOT, aa); LOG_D(PHY, "feptx_ofdm (TXPATH): frame %d, slot %d: txp (time %p) %d dB, txp (freq) %d dB\n", diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 4c2c19847c..811851b05c 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -74,9 +74,8 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs cfg->tdd_table.max_tdd_periodicity_list = calloc_or_fail(nb_slots_to_set, sizeof(nfapi_nr_max_tdd_periodicity_t)); for (int slot = 0; slot < nb_slots_to_set; slot++) { nfapi_nr_max_tdd_periodicity_t *p_list = &cfg->tdd_table.max_tdd_periodicity_list[slot]; - p_list->max_num_of_symbol_per_slot_list = - calloc_or_fail(NR_NUMBER_OF_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list)); - for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + p_list->max_num_of_symbol_per_slot_list = calloc_or_fail(NR_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list)); + for (int sym = 0; sym < NR_SYMBOLS_PER_SLOT; sym++) { // for each symbol, assign the TLV tag for usage when packing p_list->max_num_of_symbol_per_slot_list[sym].slot_config.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG; } @@ -89,9 +88,9 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs nfapi_nr_max_tdd_periodicity_t *list = &cfg->tdd_table.max_tdd_periodicity_list[slot_number]; // FULL DOWNLINK SLOTS if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_DOWNLINK_SLOT) { - for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 0; - if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) { + for (int sym = 0; sym < NR_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym % NR_SYMBOLS_PER_SLOT].slot_config.value = 0; + if ((sym + 1) % NR_SYMBOLS_PER_SLOT == 0) { slot_number++; list += 1; } @@ -101,7 +100,7 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_MIXED_SLOT) { int nrofDLSymbolsInSlot = tdd_slot_bitmap[slot_index].num_dl_symbols; int nrofULSymbolsInSlot = tdd_slot_bitmap[slot_index].num_ul_symbols; - AssertFatal(nrofDLSymbolsInSlot + nrofULSymbolsInSlot < NR_NUMBER_OF_SYMBOLS_PER_SLOT, + AssertFatal(nrofDLSymbolsInSlot + nrofULSymbolsInSlot < NR_SYMBOLS_PER_SLOT, "illegal symbol configuration DL %d, UL %d\n", nrofDLSymbolsInSlot, nrofULSymbolsInSlot); @@ -110,11 +109,11 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 0; } // Flexible Symbols - for (int sym = nrofDLSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym++) { + for (int sym = nrofDLSymbolsInSlot; sym < NR_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym++) { list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 2; } // UL Symbols - for (int sym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + for (int sym = NR_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym < NR_SYMBOLS_PER_SLOT; sym++) { list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 1; } slot_number++; @@ -122,9 +121,9 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs } // FULL UPLINK SLOTS if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_UPLINK_SLOT) { - for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 1; - if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) { + for (int sym = 0; sym < NR_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym % NR_SYMBOLS_PER_SLOT].slot_config.value = 1; + if ((sym + 1) % NR_SYMBOLS_PER_SLOT == 0) { slot_number++; list += 1; } @@ -134,14 +133,14 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs // Dump 1 period on the output for (int s = 0; s < fs->numb_slots_period; s++) { if (tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT) { - char flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT + 1]; + char flexi_slot[NR_SYMBOLS_PER_SLOT + 1]; memset(flexi_slot, 0, sizeof(flexi_slot)); - for (int symb = 0; symb < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symb++) { + for (int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { uint8_t val = cfg->tdd_table.max_tdd_periodicity_list[s].max_num_of_symbol_per_slot_list[symb].slot_config.value; char *symb_type_s[] = {"D", "U", "F"}; flexi_slot[symb] = *symb_type_s[val]; } - flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = '\0'; + flexi_slot[NR_SYMBOLS_PER_SLOT] = '\0'; LOG_I(NR_PHY, "TDD period configuration: slot %d is FLEXIBLE: %s\n", s, flexi_slot); } else { LOG_I(NR_PHY, @@ -163,25 +162,25 @@ int nr_slot_select(const nfapi_nr_config_request_scf_t *cfg, int nr_frame, int n return (NR_UPLINK_SLOT | NR_DOWNLINK_SLOT); } - for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + for (int symbol_count = 0; symbol_count < NR_SYMBOLS_PER_SLOT; symbol_count++) { if (cfg->tdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 1) { check_slot++; } } - if (check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + if (check_slot == NR_SYMBOLS_PER_SLOT) { return (NR_UPLINK_SLOT); } check_slot = 0; - for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + for (int symbol_count = 0; symbol_count < NR_SYMBOLS_PER_SLOT; symbol_count++) { if (cfg->tdd_table.max_tdd_periodicity_list[nr_slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) { check_slot++; } } - if (check_slot == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + if (check_slot == NR_SYMBOLS_PER_SLOT) { return (NR_DOWNLINK_SLOT); } else { return (NR_MIXED_SLOT); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 4e69f8fa69..3923c7ff8c 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -993,7 +993,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N int first_symb = 0, num_symb = 0; if (frame_parms->frame_type == TDD) - for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + for (int symbol_count = 0; symbol_count < NR_SYMBOLS_PER_SLOT; symbol_count++) { if (slot_conf[symbol_count].slot_config.value == 1) { if (num_symb == 0) first_symb = symbol_count; @@ -1001,7 +1001,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N } } else - num_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT; + num_symb = NR_SYMBOLS_PER_SLOT; gNB_I0_measurements(gNB, slot_rx, first_symb, num_symb, rb_mask_ul); } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index cc6a2ee23b..8bd3c08fe8 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -304,10 +304,10 @@ static void configure_srs_info(fapi_nr_ul_config_srs_pdu *srs_config_pdu, nr_srs * *********************************************************************/ bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - c16_t **txdataF, - nr_phy_data_tx_t *phy_data, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + const UE_nr_rxtx_proc_t *proc, + c16_t **txdataF, + nr_phy_data_tx_t *phy_data, + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { if(phy_data->srs_vars.active == false) { return false; @@ -383,7 +383,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n txdataF[i] = &txdataF_buf[i * samplesF_per_slot]; LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx); - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; + bool was_symbol_used[NR_SYMBOLS_PER_SLOT] = {0}; start_meas_nr_ue_phy(ue, PHY_PROC_TX); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c index 9b17546f61..0441cf47c3 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c @@ -300,7 +300,7 @@ void phy_procedures_nrUE_SL_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc tx_action = 1; } - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]; + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]; for (int i = 0; i < 14; i++) was_symbol_used[i] = true; if (tx_action) { diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index be1187f574..8d082a84aa 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -136,7 +136,7 @@ void pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data, c16_t **txdataF, - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]) + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]) { const int nr_slot_tx = proc->nr_slot_tx; NR_UE_PUCCH *pucch_vars = &phy_data->pucch_vars; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b068936739..83ee2b3dbd 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1152,7 +1152,7 @@ int main(int argc, char **argv) frame_parms->nb_prefix_samples, CYCLIC_PREFIX); } else { - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT]; + bool was_symbol_used[NR_SYMBOLS_PER_SLOT]; for (int i = 0; i < 14; i++) { was_symbol_used[i] = true; } diff --git a/openair1/SIMULATION/NR_PHY/srssim.c b/openair1/SIMULATION/NR_PHY/srssim.c index d68f925374..dae4ca8080 100644 --- a/openair1/SIMULATION/NR_PHY/srssim.c +++ b/openair1/SIMULATION/NR_PHY/srssim.c @@ -496,7 +496,7 @@ int main(int argc, char *argv[]) proc.frame_tx = frame; proc.nr_slot_tx = slot; proc.nr_slot_rx = slot; - bool was_symbol_used[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = {0}; + bool was_symbol_used[NR_SYMBOLS_PER_SLOT] = {0}; int slot_offset = get_samples_slot_timestamp(fp, slot); uint16_t ofdm_symbol_size = fp->ofdm_symbol_size; int slot_offsetF = (slot % RU_RX_SLOT_DEPTH) * fp->symbols_per_slot * ofdm_symbol_size; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index c42406149e..475badfdba 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -96,28 +96,28 @@ static void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, const frame_str for (int i = 0; i < fs->numb_slots_period; i++) { fapi_nr_max_tdd_periodicity_t *period_list = &tdd_table->max_tdd_periodicity_list[i]; period_list->max_num_of_symbol_per_slot_list = - malloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT * sizeof(*period_list->max_num_of_symbol_per_slot_list)); + malloc(NR_SYMBOLS_PER_SLOT * sizeof(*period_list->max_num_of_symbol_per_slot_list)); if (pc->tdd_slot_bitmap[i].slot_type == TDD_NR_DOWNLINK_SLOT) { - for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++) { + for (int s = 0; s < NR_SYMBOLS_PER_SLOT; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 0; } } if (pc->tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) { - for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++) { + for (int s = 0; s < NR_SYMBOLS_PER_SLOT; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 1; } } if (pc->tdd_slot_bitmap[i].slot_type == TDD_NR_MIXED_SLOT) { int dl_symb = pc->tdd_slot_bitmap[i].num_dl_symbols; int ul_symb = pc->tdd_slot_bitmap[i].num_ul_symbols; - int g_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT - dl_symb - ul_symb; + int g_symb = NR_SYMBOLS_PER_SLOT - dl_symb - ul_symb; for (int s = 0; s < dl_symb; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 0; } for (int s = dl_symb; s < dl_symb + g_symb; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 2; } - for (int s = dl_symb + g_symb; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++) { + for (int s = dl_symb + g_symb; s < NR_SYMBOLS_PER_SLOT; s++) { period_list->max_num_of_symbol_per_slot_list[s].slot_config = 1; } } diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c b/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c index 809ce054f4..75273461b1 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c @@ -77,19 +77,19 @@ void sl_set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, for(int memory_alloc = 0 ; memory_alloc < nb_slots_per_period; memory_alloc++) tdd_table->max_tdd_periodicity_list[memory_alloc].max_num_of_symbol_per_slot_list = - (fapi_nr_max_num_of_symbol_per_slot_t *) malloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT*sizeof(fapi_nr_max_num_of_symbol_per_slot_t)); + (fapi_nr_max_num_of_symbol_per_slot_t *) malloc(NR_SYMBOLS_PER_SLOT*sizeof(fapi_nr_max_num_of_symbol_per_slot_t)); int slot_number = (nb_slots_per_period - nrofUplinkSlots) - (nrofUplinkSymbols ? 1 : 0); if (nrofUplinkSymbols != 0) { - for(int number_of_symbol = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; number_of_symbol < NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) { + for(int number_of_symbol = NR_SYMBOLS_PER_SLOT - nrofUplinkSymbols; number_of_symbol < NR_SYMBOLS_PER_SLOT; number_of_symbol++) { tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol].slot_config = 1; } slot_number++; } while(slot_number < nb_slots_per_period) { - for (int number_of_symbol = 0; number_of_symbol < nrofUplinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; number_of_symbol++) { - tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol%NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config = 1; - if((number_of_symbol + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) + for (int number_of_symbol = 0; number_of_symbol < nrofUplinkSlots * NR_SYMBOLS_PER_SLOT; number_of_symbol++) { + tdd_table->max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[number_of_symbol%NR_SYMBOLS_PER_SLOT].slot_config = 1; + if((number_of_symbol + 1) % NR_SYMBOLS_PER_SLOT == 0) slot_number++; } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index a93ad9f8d2..1d534ee80d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -425,8 +425,8 @@ static bool check_mixed_slot_prach(frame_structure_t *fs, int slot, int start_pr tdd_bitmap_t *bitmap = &fs->period_cfg.tdd_slot_bitmap[slot % fs->numb_slots_period]; if (bitmap->num_ul_symbols == 0) return false; - int ul_end = NR_NUMBER_OF_SYMBOLS_PER_SLOT - 1; - int ul_start = NR_NUMBER_OF_SYMBOLS_PER_SLOT - bitmap->num_ul_symbols; + int ul_end = NR_SYMBOLS_PER_SLOT - 1; + int ul_start = NR_SYMBOLS_PER_SLOT - bitmap->num_ul_symbols; if (start_prach < ul_start || end_prach > ul_end) return false; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl.c index 71e4c7fe25..9f22cbc882 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler_sl.c @@ -63,9 +63,9 @@ static uint8_t sl_get_elapsed_slots(uint32_t slot, uint32_t sl_slot_bitmap) */ static uint8_t sl_determine_if_sidelink_slot(uint8_t sl_startsym, uint8_t sl_lensym, uint8_t num_ulsym) { - uint8_t ul_startsym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - num_ulsym; + uint8_t ul_startsym = NR_SYMBOLS_PER_SLOT - num_ulsym; - if ((sl_startsym >= ul_startsym) && (sl_lensym <= NR_NUMBER_OF_SYMBOLS_PER_SLOT)) { + if ((sl_startsym >= ul_startsym) && (sl_lensym <= NR_SYMBOLS_PER_SLOT)) { LOG_D(MAC, "MIXED SLOT is a SIDELINK SLOT. Sidelink Symbols: %d-%d, Uplink Symbols: %d-%d\n", sl_startsym, @@ -107,13 +107,13 @@ int sl_nr_ue_slot_select(const sl_nr_phy_config_request_t *cfg, int slot, uint8_ const fapi_nr_max_tdd_periodicity_t *current_slot = &tdd_table->max_tdd_periodicity_list[rel_slot]; - for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + for (int symbol_count = 0; symbol_count < NR_SYMBOLS_PER_SLOT; symbol_count++) { if (current_slot->max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { ul_sym++; } } - if (ul_sym == NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + if (ul_sym == NR_SYMBOLS_PER_SLOT) { slot_type = NR_SIDELINK_SLOT; } else if (ul_sym) { slot_type = sl_determine_if_sidelink_slot(cfg->sl_bwp_config.sl_start_symbol, cfg->sl_bwp_config.sl_num_symbols, ul_sym); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 99f0e9bb3c..44fd2546cb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1024,7 +1024,7 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, int s = get_slot_idx_in_period(temp_slot, fs); const tdd_bitmap_t *bm = &fs->period_cfg.tdd_slot_bitmap[s]; bool is_mixed = is_mixed_slot(s, fs); - uint16_t slot_mask = is_mixed ? SL_to_bitmap(NR_NUMBER_OF_SYMBOLS_PER_SLOT - bm->num_ul_symbols, bm->num_ul_symbols) : 0x3fff; + uint16_t slot_mask = is_mixed ? SL_to_bitmap(NR_SYMBOLS_PER_SLOT - bm->num_ul_symbols, bm->num_ul_symbols) : 0x3fff; long startSymbolAndLength = tda_list->list.array[i]->startSymbolAndLength; int start, nr; SLIV2SL(startSymbolAndLength, &start, &nr); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index e511850414..c6d130cdaf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -101,7 +101,7 @@ static void fill_ssb_vrb_map(NR_COMMON_channels_t *cc, uint16_t *vrb_map = cc[CC_id].vrb_map[beam]; const int extra_prb = ssb_subcarrier_offset > 0; for (int rb = 0; rb < 20 + extra_prb; rb++) - vrb_map[rbStart + rb] = SL_to_bitmap(symStart % NR_NUMBER_OF_SYMBOLS_PER_SLOT, 4); + vrb_map[rbStart + rb] = SL_to_bitmap(symStart % NR_SYMBOLS_PER_SLOT, 4); } static int encode_mib(NR_BCCH_BCH_Message_t *mib, frame_t frame, uint8_t *buffer, int buf_size) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index f23dfe8b30..fdec1d0c6f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -104,7 +104,7 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); // select beam for PDSCH in current slot based on SSB beam - if ((ssb_start_symbol / NR_NUMBER_OF_SYMBOLS_PER_SLOT) == (slot % mac->frame_structure.numb_slots_period)) { + if ((ssb_start_symbol / NR_SYMBOLS_PER_SLOT) == (slot % mac->frame_structure.numb_slots_period)) { ssb_idx_beam = i_ssb; break; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 1afa2d1502..4c7cf1acf1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -479,7 +479,7 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac, AssertFatal(beam.idx >= 0, "Cannot allocate SRS in any available beam\n"); uint16_t *vrb_map_UL = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][buffer_index * MAX_BWP_SIZE]; uint16_t num = 1 << srs_pdu->num_symbols; // 0,1,2 means 1,2,4 symbols, see 222.10.04 table 3-105 - const uint8_t l0 = NR_NUMBER_OF_SYMBOLS_PER_SLOT - 1 - srs_pdu->time_start_position; + const uint8_t l0 = NR_SYMBOLS_PER_SLOT - 1 - srs_pdu->time_start_position; uint16_t mask = SL_to_bitmap(l0, num); DevAssert(mask != 0); for (int i = 0; i < srs_pdu->bwp_size; ++i) { diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 054703c2e2..313a6d5d3b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -1145,7 +1145,7 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay, i int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; // make TDA for the mixed slot - long mixed_sliv = get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); + long mixed_sliv = get_SLIV(NR_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); int mixed_min_ul_symb = 3; // need at least two symbols PUSCH + PUCCH bool has_ul_mixed = ul_symb >= mixed_min_ul_symb; if (has_ul_mixed && (k2 <= N_dl1 || (p2 && N_ul2 == 0))) { diff --git a/openair2/RRC/NR_UE/verify_RRC.c b/openair2/RRC/NR_UE/verify_RRC.c index b33da53dae..83a325d255 100644 --- a/openair2/RRC/NR_UE/verify_RRC.c +++ b/openair2/RRC/NR_UE/verify_RRC.c @@ -252,9 +252,9 @@ static bool check_srs_config(NR_SRS_Config_t *srs_Config) if (srs_Config->srs_ResourceToAddModList) { for (int i = 0; i < srs_Config->srs_ResourceToAddModList->list.count; i++) { NR_SRS_Resource_t *res = srs_Config->srs_ResourceToAddModList->list.array[i]; - int start = NR_NUMBER_OF_SYMBOLS_PER_SLOT - res->resourceMapping.startPosition - 1; + int start = NR_SYMBOLS_PER_SLOT - res->resourceMapping.startPosition - 1; int num = 1 << res->resourceMapping.nrofSymbols; - if (start + num > NR_NUMBER_OF_SYMBOLS_PER_SLOT) { + if (start + num > NR_SYMBOLS_PER_SLOT) { LOG_E(NR_RRC, "The configured SRS resource exceeds the slot boundary\n"); return false; } From edef0750003e7844c7266456bd0b647ebcdd475a Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 5 Mar 2026 10:06:46 +0100 Subject: [PATCH 04/30] reduce the use of NR_SYMBOLS_PER_SLOT in favor of the value in frame_parms --- executables/nr-ru.c | 2 +- openair1/PHY/INIT/nr_init.c | 2 +- openair1/PHY/INIT/nr_parms.c | 6 ++-- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 4 +-- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 8 ++--- openair1/PHY/NR_TRANSPORT/nr_prach.c | 2 +- openair1/PHY/NR_TRANSPORT/nr_ulsch.c | 2 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 4 +-- openair1/PHY/NR_TRANSPORT/srs_rx.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 35 ++++++++++--------- .../NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 2 +- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 22 ++++++------ openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 26 ++++++-------- .../PHY/nr_phy_common/src/nr_phy_common_srs.c | 14 ++++---- openair1/SCHED_NR/nr_ru_procedures.c | 8 ++--- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 9 +++-- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 19 +++++----- openair1/SIMULATION/NR_PHY/psbchsim.c | 2 +- 19 files changed, 82 insertions(+), 89 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 2f5f136d17..1d1b3ca014 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -538,7 +538,7 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp) if(slot_type == NR_MIXED_SLOT) { int txsymb = 0; - for(int symbol_count = 0; symbol_count < NR_SYMBOLS_PER_SLOT; symbol_count++) { + for(int symbol_count = 0; symbol_count < fp->symbols_per_slot; symbol_count++) { if (cfg->tdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value == 0) txsymb++; } diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index e140b9dab0..95756fc80c 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -436,7 +436,7 @@ void init_nr_transport(PHY_VARS_gNB *gNB) int nb_ul_slots_period = 0; if (cfg->cell_config.frame_duplex_type.value) { for(int i = 0; i < nb_slots_per_period; i++) { - for(int j = 0; j < NR_SYMBOLS_PER_SLOT; j++) { + for(int j = 0; j < fp->symbols_per_slot; j++) { if(cfg->tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[j].slot_config.value == 1) { // UL symbol nb_ul_slots_period++; break; diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 0e39e19d9e..f22da3d204 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -409,7 +409,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fapi_nr_config_request_t* conf set_scs_parameters(fp, fp->numerology_index, N_RB, config->ssb_table.ssb_case); fp->slots_per_frame = 10* fp->slots_per_subframe; - fp->symbols_per_slot = ((Ncp == NR_NORMAL)? 14 : 12); // to redefine for different slot formats + fp->symbols_per_slot = ((Ncp == NR_NORMAL)? NR_SYMBOLS_PER_SLOT : NR_SYMBOLS_PER_SLOT_EXTENDED_CP); fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe; fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP; fp->samples_per_slot_wCP = fp->symbols_per_slot*fp->ofdm_symbol_size; @@ -469,7 +469,7 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, const nrUE_cell_p set_Lmax(frame_parms); frame_parms->slots_per_frame = 10* frame_parms->slots_per_subframe; - frame_parms->symbols_per_slot = ((frame_parms->Ncp == NR_NORMAL)? 14 : 12); // to redefine for different slot formats + frame_parms->symbols_per_slot = ((frame_parms->Ncp == NR_NORMAL)? NR_SYMBOLS_PER_SLOT : NR_SYMBOLS_PER_SLOT_EXTENDED_CP); frame_parms->samples_per_subframe_wCP = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot * frame_parms->slots_per_subframe; frame_parms->samples_per_frame_wCP = 10 * frame_parms->samples_per_subframe_wCP; frame_parms->samples_per_slot_wCP = frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; @@ -570,7 +570,7 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, sl_set_scs_parameters(fp, fp->numerology_index, fp->N_RB_SL); fp->slots_per_frame = 10 * fp->slots_per_subframe; - fp->symbols_per_slot = ((fp->Ncp == NR_NORMAL) ? 14 : 12); // to redefine for different slot formats + fp->symbols_per_slot = ((fp->Ncp == NR_NORMAL) ? NR_SYMBOLS_PER_SLOT : NR_SYMBOLS_PER_SLOT_EXTENDED_CP); fp->samples_per_subframe_wCP = fp->ofdm_symbol_size * fp->symbols_per_slot * fp->slots_per_subframe; fp->samples_per_frame_wCP = 10 * fp->samples_per_subframe_wCP; fp->samples_per_slot_wCP = fp->symbols_per_slot * fp->ofdm_symbol_size; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 24cf6b72b6..10da936391 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -554,7 +554,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC time_stats_t *dlsch_scrambling_stats = &gNB->dlsch_scrambling_stats; time_stats_t *dlsch_modulation_stats = &gNB->dlsch_modulation_stats; const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; - const int layerSz = frame_parms->N_RB_DL * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB; + const int layerSz = frame_parms->N_RB_DL * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB; const int symbol_sz=frame_parms->ofdm_symbol_size; const int dmrs_Type = rel15->dmrsConfigType; const int nb_re_dmrs = rel15->numDmrsCdmGrpsNoData * (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4); @@ -765,7 +765,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC /* output and its parts for each dlsch should be aligned on 64 bytes (or 8 * 64 bits) * should remain a multiple of 8 * 64 with enough offset to fit each dlsch */ - uint32_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers; + uint32_t size_output_tb = rel15->rbSize * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers; return ((size_output_tb + 511) >> 9) << 6; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index b2e7772a36..c2af8481c3 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -55,7 +55,7 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM dlsch->b = NULL; } if (dlsch->f) { - free16(dlsch->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + free16(dlsch->f, N_RB * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); dlsch->f = NULL; } for (int r = 0; r < a_segments; r++) { @@ -94,9 +94,9 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) bzero(dlsch.c[r], 8448); } - dlsch.f = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + dlsch.f = malloc16(N_RB * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); AssertFatal(dlsch.f, "cannot allocate dlsch->f\n"); - bzero(dlsch.f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + bzero(dlsch.f, N_RB * frame_parms->symbols_per_slot * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); return (dlsch); } @@ -262,7 +262,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, /* output and its parts for each dlsch should be aligned on 64 bytes (or 8 * 64 bits) * => dlsch_offset should remain a multiple of 8 * 64 with enough offset to fit each dlsch */ - const size_t dlsch_size = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * rel15->qamModOrder[0] * rel15->nrOfLayers; + const size_t dlsch_size = rel15->rbSize * gNB->frame_parms.symbols_per_slot * NR_NB_SC_PER_RB * rel15->qamModOrder[0] * rel15->nrOfLayers; dlsch_offset += ceil_mod(dlsch_size, 8 * 64); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 5395c33df9..7b306e547a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -105,7 +105,7 @@ prach_item_t *nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_n fapi_beam_idx, &gNB->common_vars, Slot, - NR_SYMBOLS_PER_SLOT, + gNB->frame_parms.symbols_per_slot, bitmap); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index 72dccf4a40..991dc12992 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -160,7 +160,7 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t fapi_beam_idx, &gNB->common_vars, slot, - NR_SYMBOLS_PER_SLOT, + gNB->frame_parms.symbols_per_slot, bitmap); } ulsch->frame = frame; diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 51cb354f98..08ac27fde1 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -73,7 +73,7 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t fapi_beam_idx, &gNB->common_vars, slot, - NR_SYMBOLS_PER_SLOT, + gNB->frame_parms.symbols_per_slot, bitmap); } memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); @@ -1069,7 +1069,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, // first compute DMRS component const int scramble = pucch_pdu->dmrs_scrambling_id * 2; uint32_t x2 = - ((1ULL << 17) * ((NR_SYMBOLS_PER_SLOT * slot + pucch_pdu->start_symbol_index + symb + 1) * (scramble + 1)) + ((1ULL << 17) * ((frame_parms->symbols_per_slot * slot + pucch_pdu->start_symbol_index + symb + 1) * (scramble + 1)) + scramble) % (1U << 31); // c_init calculation according to TS38.211 subclause #ifdef DEBUG_NR_PUCCH_RX diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index 05cddefd20..a5c7455274 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -63,7 +63,7 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu fapi_beam_idx, &gNB->common_vars, slot, - NR_SYMBOLS_PER_SLOT, + gNB->frame_parms.symbols_per_slot, bitmap); } memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t)); diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 3004728091..ff52d4e47a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -330,7 +330,7 @@ static int nr_csi_rs_channel_estimation( } #ifdef NR_CSIRS_DEBUG - for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { + for(int symb = 0; symb < fp->symbols_per_slot; symb++) { if(!is_csi_rs_in_symbol(*csirs_config_pdu,symb)) { continue; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 65a0247046..46b88aa354 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -345,8 +345,7 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, // generate pilot c16_t pilot[(n_rb + dmrs_ref) * 3] __attribute__((aligned(16))); // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS - const uint32_t *gold = - nr_gold_pdcch(ue->frame_parms.N_RB_DL, ue->frame_parms.symbols_per_slot, scrambling_id, proc->nr_slot_rx, symbol); + const uint32_t *gold = nr_gold_pdcch(fp->N_RB_DL, fp->symbols_per_slot, scrambling_id, proc->nr_slot_rx, symbol); nr_pdcch_dmrs_ref(gold, pilot, n_rb + dmrs_ref); nr_pdcch_channel_estimation(ue, n_rb, @@ -363,7 +362,7 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, __attribute__((aligned(32))) c16_t rxdataF_ext[fp->nb_antennas_rx][rx_size]; __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[fp->nb_antennas_rx][rx_size]; - nr_pdcch_extract_rbs_single(ue->frame_parms.ofdm_symbol_size, + nr_pdcch_extract_rbs_single(fp->ofdm_symbol_size, rxdataF, pdcch_est_size, pdcch_dl_ch_estimates, @@ -401,16 +400,18 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, nr_pdcch_llr(llr_size_symbol, rxdataF_comp[0], llr); } -bool is_start_symbol_in_ss(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, const int symbol) +static bool is_start_symbol_in_ss(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, const int symbol, const int nb_symb_slot) { - return ((ss->coreset.StartSymbolBitmap >> (NR_SYMBOLS_PER_SLOT - 1 - symbol)) & 1); + return ((ss->coreset.StartSymbolBitmap >> (nb_symb_slot - 1 - symbol)) & 1); } -int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, uint8_t start_symb[NR_SYMBOLS_PER_SLOT]) +static int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, + int nb_symb_slot, + uint8_t start_symb[nb_symb_slot]) { int sum = 0; - for (int s = 0; s < NR_SYMBOLS_PER_SLOT; s++) { - if (is_start_symbol_in_ss(ss, s)) { + for (int s = 0; s < nb_symb_slot; s++) { + if (is_start_symbol_in_ss(ss, s, nb_symb_slot)) { if (start_symb != NULL) start_symb[sum] = s; sum++; @@ -420,22 +421,22 @@ int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, return sum; } -int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config) +int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb_slot) { int monOcc = 0; for (int ss = 0; ss < phy_pdcch_config->nb_search_space; ss++) { - monOcc = max(monOcc, get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss], NULL)); + monOcc = max(monOcc, get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss], nb_symb_slot, NULL)); } return monOcc; } -void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int *first_symb, int *last_symb) +void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb_slot, int *first_symb, int *last_symb) { - *first_symb = NR_SYMBOLS_PER_SLOT; // max first pdcch symbol + *first_symb = nb_symb_slot; // max first pdcch symbol *last_symb = 0; // min last pdcch symbol for (int ss = 0; ss < phy_pdcch_config->nb_search_space; ss++) { - for (int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { - if (is_start_symbol_in_ss(&phy_pdcch_config->pdcch_config[ss], symb)) { + for (int symb = 0; symb < nb_symb_slot; symb++) { + if (is_start_symbol_in_ss(&phy_pdcch_config->pdcch_config[ss], symb, nb_symb_slot)) { const int duration = phy_pdcch_config->pdcch_config[ss].coreset.duration; *first_symb = min(*first_symb, symb); *last_symb = max(*last_symb, symb + duration - 1); @@ -460,7 +461,9 @@ void nr_pdcch_generate_llr(PHY_VARS_NR_UE *ue, // Loop over search spaces for (int ss_idx = 0; ss_idx < phy_pdcch_config->nb_search_space; ss_idx++) { uint8_t start_symb[NR_SYMBOLS_PER_SLOT] = {0}; - const int num_monOcc = get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss_idx], start_symb); + const int num_monOcc = get_pdcch_mon_occasions_slot(&phy_pdcch_config->pdcch_config[ss_idx], + ue->frame_parms.symbols_per_slot, + start_symb); // Loop over monitoring occations within the slot in this ss for (int occ = 0; occ < num_monOcc; occ++) { const int first_symb = start_symb[occ]; @@ -609,7 +612,7 @@ void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc, for (int ss_idx = 0; ss_idx < phy_pdcch_config->nb_search_space; ss_idx++) { fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &phy_pdcch_config->pdcch_config[ss_idx]; uint8_t unused_start_symb[NR_SYMBOLS_PER_SLOT] = {0}; - const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, unused_start_symb); + const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, ue->frame_parms.symbols_per_slot, unused_start_symb); const int llr_stride = llr_size / rel15->coreset.duration; int n_rb, cset_start; get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index b46d89943c..8e893226a3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -701,7 +701,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, UEunlockScopeData(ue, pdschRxdataF_comp) } } else { - UEscopeCopy(ue, pdschRxdataF_comp, rxdataF_comp[0], sizeof(c16_t), nbRx, rx_size_symbol * NR_SYMBOLS_PER_SLOT, 0); + UEscopeCopy(ue, pdschRxdataF_comp, rxdataF_comp[0], sizeof(c16_t), nbRx, rx_size_symbol * fp->symbols_per_slot, 0); } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index d80a99bb73..d77a168c41 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -69,11 +69,9 @@ typedef struct pdsch_scope_req_s { void nr_ue_dlsch_init(NR_UE_DLSCH_t *dlsch_list, int num_dlsch, uint8_t max_ldpc_iterations); void nr_conjch0_mult_ch1(c16_t *ch0, c16_t *ch1, c16_t *ch0conj_ch1, unsigned short nb_rb, unsigned char output_shift0); -void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int *first_symb, int *last_symb); +void set_first_last_pdcch_symb(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int symb_slot, int *first_symb, int *last_symb); -int get_pdcch_mon_occasions_slot(const fapi_nr_dl_config_dci_dl_pdu_rel15_t *ss, uint8_t start_symb[NR_SYMBOLS_PER_SLOT]); - -int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config); +int get_max_pdcch_monOcc(const NR_UE_PDCCH_CONFIG *phy_pdcch_config, int nb_symb_slot); /** \brief This is the alternative top-level entry point for DLSCH decoding in UE. It handles all the HARQ processes in only one call. The routine first @@ -167,14 +165,14 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, /** \brief This function does IFFT for PUSCH */ -uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, - const NR_DL_FRAME_PARMS *frame_parms, - const uint8_t n_antenna_ports, - c16_t **txdataF, - c16_t **txdata, - uint32_t linktype, - bool was_symbol_used[NR_SYMBOLS_PER_SLOT], - bool no_phase_pre_comp); +void nr_tx_rotation_and_ofdm_mod(const uint8_t slot, + const NR_DL_FRAME_PARMS *frame_parms, + const uint8_t n_antenna_ports, + c16_t **txdataF, + c16_t **txdata, + uint32_t linktype, + bool was_symbol_used[NR_SYMBOLS_PER_SLOT], + bool no_phase_pre_comp); bool ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 25b5766f07..bf1ddaec20 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1603,19 +1603,19 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, stop_meas_nr_ue_phy(UE, PUSCH_PROC_STATS); } -uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, - const NR_DL_FRAME_PARMS *frame_parms, - const uint8_t n_antenna_ports, - c16_t **txdataF, - c16_t **txdata, - uint32_t linktype, - bool was_symbol_used[NR_SYMBOLS_PER_SLOT], - bool no_phase_pre_comp) +void nr_tx_rotation_and_ofdm_mod(const uint8_t slot, + const NR_DL_FRAME_PARMS *frame_parms, + const uint8_t n_antenna_ports, + c16_t **txdataF, + c16_t **txdata, + uint32_t linktype, + bool was_symbol_used[NR_SYMBOLS_PER_SLOT], + bool no_phase_pre_comp) { int N_RB = (linktype == link_type_sl) ? frame_parms->N_RB_SL : frame_parms->N_RB_UL; if (!no_phase_pre_comp) { - for (int i = 0; i < NR_SYMBOLS_PER_SLOT; i++) { + for (int i = 0; i < frame_parms->symbols_per_slot; i++) { if (was_symbol_used[i] == false) continue; for (int ap = 0; ap < n_antenna_ports; ap++) { @@ -1626,7 +1626,7 @@ uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, for (int ap = 0; ap < n_antenna_ports; ap++) { if (frame_parms->Ncp == 1) { // extended cyclic prefix - for (int i = 0; i < NR_SYMBOLS_PER_SLOT_EXTENDED_CP; i++) { + for (int i = 0; i < frame_parms->symbols_per_slot; i++) { if (was_symbol_used[i] == false) { memset(&txdata[ap][(frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples) * i], 0, @@ -1641,11 +1641,7 @@ uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, CYCLIC_PREFIX); } } else { // normal cyclic prefix - nr_normal_prefix_mod(txdataF[ap], txdata[ap], NR_SYMBOLS_PER_SLOT, frame_parms, slot, was_symbol_used); + nr_normal_prefix_mod(txdataF[ap], txdata[ap], frame_parms->symbols_per_slot, frame_parms, slot, was_symbol_used); } } - - /////////// - //////////////////////////////////////////////////// - return 0; } diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c index f258b92205..547c4bdf18 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c @@ -30,18 +30,18 @@ static const uint16_t srs_max_number_cs[3] = {8, 12, 6}; //#define SRS_DEBUG -static int group_number_hopping(int slot_number, uint8_t n_ID_SRS, uint8_t l0, uint8_t l_line) +static int group_number_hopping(int slot_number, uint8_t n_ID_SRS, uint8_t l0, uint8_t l_line, int symb_slot) { // Pseudo-random sequence c(i) defined by TS 38.211 - Section 5.2.1 uint32_t cinit = n_ID_SRS; - uint8_t c_last_index = 8 * (slot_number * NR_SYMBOLS_PER_SLOT + l0 + l_line) + 7; + uint8_t c_last_index = 8 * (slot_number * symb_slot + l0 + l_line) + 7; uint32_t *c_sequence = calloc(c_last_index + 1, sizeof(uint32_t)); pseudo_random_sequence(c_last_index + 1, c_sequence, cinit); // TS 38.211 - 6.4.1.4.2 Sequence generation uint32_t f_gh = 0; for (int m = 0; m <= 7; m++) { - f_gh += c_sequence[8 * (slot_number * NR_SYMBOLS_PER_SLOT + l0 + l_line) + m] << m; + f_gh += c_sequence[8 * (slot_number * symb_slot + l0 + l_line) + m] << m; } f_gh = f_gh % 30; int u = (f_gh + n_ID_SRS) % U_GROUP_NUMBER; @@ -49,13 +49,13 @@ static int group_number_hopping(int slot_number, uint8_t n_ID_SRS, uint8_t l0, u return u; } -static int sequence_number_hopping(int slot_number, uint8_t n_ID_SRS, uint16_t M_sc_b_SRS, uint8_t l0, uint8_t l_line) +static int sequence_number_hopping(int slot_number, int n_ID_SRS, int M_sc_b_SRS, int l0, int l_line, int symb_slot) { int v = 0; if (M_sc_b_SRS > 6 * NR_NB_SC_PER_RB) { // Pseudo-random sequence c(i) defined by TS 38.211 - Section 5.2.1 uint32_t cinit = n_ID_SRS; - uint8_t c_last_index = (slot_number * NR_SYMBOLS_PER_SLOT + l0 + l_line); + uint8_t c_last_index = (slot_number * symb_slot + l0 + l_line); uint32_t *c_sequence = calloc(c_last_index + 1, sizeof(uint32_t)); pseudo_random_sequence(c_last_index + 1, c_sequence, cinit); // TS 38.211 - 6.4.1.4.2 Sequence generation @@ -255,12 +255,12 @@ bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms, v = 0; break; case groupHopping: - u = group_number_hopping(slot_number, nr_srs_info->n_ID_SRS, l0, l_line); + u = group_number_hopping(slot_number, nr_srs_info->n_ID_SRS, l0, l_line, frame_parms->symbols_per_slot); v = 0; break; case sequenceHopping: u = nr_srs_info->n_ID_SRS % U_GROUP_NUMBER; - v = sequence_number_hopping(slot_number, nr_srs_info->n_ID_SRS, M_sc_b_SRS, l0, l_line); + v = sequence_number_hopping(slot_number, nr_srs_info->n_ID_SRS, M_sc_b_SRS, l0, l_line, frame_parms->symbols_per_slot); break; default: LOG_E(NR_PHY, "generate_srs: unknown hopping setting %d !\n", nr_srs_info->groupOrSequenceHopping); diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index e19b332c80..d63de51862 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -145,19 +145,17 @@ void nr_feptx0(RU_t *ru, int tti_tx, int first_symbol, int num_symbols, int aa) void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) { nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config; - NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; - int cyclic_prefix_type = NFAPI_CP_NORMAL; + NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; unsigned int aa=0; - int slot_sizeF = (fp->ofdm_symbol_size)* - ((cyclic_prefix_type == 1) ? 12 : 14); + int slot_sizeF = fp->ofdm_symbol_size * fp->symbols_per_slot; int slot = tti_tx; int *txdata = &ru->common.txdata[aa][get_samples_slot_timestamp(fp, slot)]; if (nr_slot_select(cfg,frame_tx,slot) == NR_UPLINK_SLOT) return; - nr_feptx0(ru, slot, 0, NR_SYMBOLS_PER_SLOT, aa); + nr_feptx0(ru, slot, 0, fp->symbols_per_slot, aa); LOG_D(PHY, "feptx_ofdm (TXPATH): frame %d, slot %d: txp (time %p) %d dB, txp (freq) %d dB\n", diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 3923c7ff8c..f28e7de200 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -980,7 +980,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; const uint16_t ofdm_symbol_size = frame_parms->ofdm_symbol_size; - const int nb_symb = frame_parms->symbols_per_slot; const uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); { @@ -993,7 +992,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N int first_symb = 0, num_symb = 0; if (frame_parms->frame_type == TDD) - for (int symbol_count = 0; symbol_count < NR_SYMBOLS_PER_SLOT; symbol_count++) { + for (int symbol_count = 0; symbol_count < frame_parms->symbols_per_slot; symbol_count++) { if (slot_conf[symbol_count].slot_config.value == 1) { if (num_symb == 0) first_symb = symbol_count; @@ -1001,11 +1000,11 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N } } else - num_symb = NR_SYMBOLS_PER_SLOT; + num_symb = frame_parms->symbols_per_slot; gNB_I0_measurements(gNB, slot_rx, first_symb, num_symb, rb_mask_ul); } - const int soffset = (slot_rx & 3) * nb_symb * ofdm_symbol_size; + const int soffset = (slot_rx & 3) * frame_parms->symbols_per_slot * ofdm_symbol_size; start_meas(&gNB->phy_proc_rx); for (int i = 0; i < gNB->max_nb_pucch; i++) { @@ -1368,7 +1367,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), - T_BUFFER(&gNB->common_vars.rxdataF[0][0][0], nb_symb * ofdm_symbol_size * 4)); + T_BUFFER(&gNB->common_vars.rxdataF[0][0][0], frame_parms->symbols_per_slot * ofdm_symbol_size * 4)); } return pusch_DTX; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 8bd3c08fe8..fb99c29965 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -375,7 +375,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, n T(T_UE_PHY_UL_TICK, T_INT(ue->Mod_id), T_INT(frame_tx % 1024), T_INT(slot_tx)); #endif - const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * ue->frame_parms.ofdm_symbol_size; + const int samplesF_per_slot = ue->frame_parms.symbols_per_slot * ue->frame_parms.ofdm_symbol_size; c16_t txdataF_buf[ue->frame_parms.nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32))); memset(txdataF_buf, 0, sizeof(txdataF_buf)); c16_t *txdataF[ue->frame_parms.nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */ @@ -618,7 +618,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, toFree2, dlsch[0].Nl, ue->frame_parms.nb_antennas_rx, - rx_size_symbol * NR_SYMBOLS_PER_SLOT, + rx_size_symbol * ue->frame_parms.symbols_per_slot, false); uint32_t nvar = 0; @@ -1027,22 +1027,21 @@ void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ /* process PDCCH */ LOG_D(PHY, " ------ --> PDCCH ChannelComp/LLR Frame.slot %d.%d ------ \n", proc->frame_rx % 1024, proc->nr_slot_rx); start_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); - int num_monitoring_occ = get_max_pdcch_monOcc(phy_pdcch_config); + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; + int num_monitoring_occ = get_max_pdcch_monOcc(phy_pdcch_config, fp->symbols_per_slot); int max_nb_symb_pdcch = get_max_pdcch_symb(phy_pdcch_config); int llr_size_symbol = get_pdcch_max_rbs(phy_pdcch_config) * 9; c16_t pdcch_llr[phy_pdcch_config->nb_search_space][num_monitoring_occ][max_nb_symb_pdcch * llr_size_symbol]; - int start_symb_pdcch, last_symb_pdcch; - set_first_last_pdcch_symb(phy_pdcch_config, &start_symb_pdcch, &last_symb_pdcch); + set_first_last_pdcch_symb(phy_pdcch_config, fp->symbols_per_slot, &start_symb_pdcch, &last_symb_pdcch); /* Temporarily loop over symbols in the slot, perform OFDM demod and process PDCCH. When symbol based proc design is fully merged, this function will be called to process only one symbol and OFDM demod will be removed from here. */ - const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP; - __attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; + const uint32_t rxdataF_sz = fp->samples_per_slot_wCP; + __attribute__((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz]; for (int symbol = start_symb_pdcch; symbol <= last_symb_pdcch; symbol++) { - NR_DL_FRAME_PARMS *fp = &ue->frame_parms; nr_slot_fep(ue, fp, proc->nr_slot_rx, symbol, rxdataF, link_type_dl, 0, ue->common_vars.rxdata); __attribute__((aligned(32))) c16_t rxdataF_symb[fp->nb_antennas_rx][((fp->ofdm_symbol_size + 7) / 8) * 8]; @@ -1058,7 +1057,7 @@ void pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ stop_meas_nr_ue_phy(ue, DLSCH_RX_PDCCH_STATS); TracyCZoneEnd(ctx); if (ue->phy_sim_rxdataF) - memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * max_nb_symb_pdcch * ue->frame_parms.ofdm_symbol_size); + memcpy(ue->phy_sim_rxdataF, rxdataF[0], sizeof(int32_t) * max_nb_symb_pdcch * fp->ofdm_symbol_size); } int pbch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) @@ -1248,7 +1247,7 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_ // do procedures for CSI-RS if (phy_data->csirs_vars.active == 1) { - for(int symb = 0; symb < NR_SYMBOLS_PER_SLOT; symb++) { + for(int symb = 0; symb < ue->frame_parms.symbols_per_slot; symb++) { if(is_csi_rs_in_symbol(phy_data->csirs_vars.csirs_config_pdu, symb)) { if (!slot_fep_map[symb]) { nr_slot_fep(ue, &ue->frame_parms, proc->nr_slot_rx, symb, rxdataF, link_type_dl, 0, ue->common_vars.rxdata); diff --git a/openair1/SIMULATION/NR_PHY/psbchsim.c b/openair1/SIMULATION/NR_PHY/psbchsim.c index cb78915cbb..d4755eb960 100644 --- a/openair1/SIMULATION/NR_PHY/psbchsim.c +++ b/openair1/SIMULATION/NR_PHY/psbchsim.c @@ -246,7 +246,7 @@ static int freq_domain_loopback(PHY_VARS_NR_UE *UE_tx, PHY_VARS_NR_UE *UE_rx, in sl_ue2->sl_config.sl_sync_source.rx_slss_id); NR_DL_FRAME_PARMS *fp = &sl_ue1->sl_frame_params; - const int samplesF_per_slot = NR_SYMBOLS_PER_SLOT * fp->ofdm_symbol_size; + const int samplesF_per_slot = fp->symbols_per_slot * fp->ofdm_symbol_size; c16_t txdataF_buf[fp->nb_antennas_tx * samplesF_per_slot] __attribute__((aligned(32))); memset(txdataF_buf, 0, sizeof(txdataF_buf)); c16_t *txdataF[fp->nb_antennas_tx]; /* workaround to be compatible with current txdataF usage in all tx procedures. */ From c84c858c56b4eeb25e46e179b3791fd23c75a48f Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 22 Sep 2025 20:57:07 +0000 Subject: [PATCH 05/30] phy: use smaller buffer for txdataF It is enough to allocate txdataF for one slot. --- openair1/PHY/INIT/nr_init.c | 2 +- openair1/PHY/INIT/nr_init_ru.c | 2 +- openair1/PHY/INIT/nr_init_ue.c | 2 +- openair1/PHY/NR_TRANSPORT/nr_dci.c | 3 +-- openair1/PHY/NR_TRANSPORT/nr_dci.h | 1 - openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 3 +-- openair1/PHY/NR_UE_TRANSPORT/csi_rx.c | 3 +-- .../nr_phy_common/src/nr_phy_common_csirs.c | 6 +---- openair1/SCHED_NR/nr_ru_procedures.c | 14 +++++------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 22 +++++++++---------- openair1/SIMULATION/NR_PHY/dlsim.c | 12 +++++----- openair1/SIMULATION/NR_PHY/pbchsim.c | 6 ++--- 12 files changed, 31 insertions(+), 45 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index d8b34b2598..bb7e4c3f0c 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -185,7 +185,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) for (int i = 0; i < common_vars->num_beams_period; i++) { common_vars->txdataF[i] = (c16_t**)malloc16_clear(Ptx * sizeof(c16_t*)); for (int j = 0; j < Ptx; j++) - common_vars->txdataF[i][j] = (c16_t*)malloc16_clear(fp->samples_per_frame_wCP * sizeof(c16_t)); + common_vars->txdataF[i][j] = (c16_t*)malloc16_clear(fp->samples_per_slot_wCP * sizeof(c16_t)); } common_vars->debugBuff = (int32_t*)malloc16_clear(fp->samples_per_frame*sizeof(int32_t)*100); common_vars->debugBuff_sample_offset = 0; diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 48621afee4..21b564d3c2 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -97,7 +97,7 @@ void nr_phy_init_RU(RU_t *ru) ru->common.txdataF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*)); // [hna] samples_per_frame without CP for(int i = 0; i < ru->nb_tx; ++i) - ru->common.txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP * sizeof(int32_t)); + ru->common.txdataF[i] = (int32_t *)malloc16_clear(fp->samples_per_slot_wCP * sizeof(int32_t)); // allocate IFFT input buffers (TX) ru->common.txdataF_BF = (int32_t **)malloc16(nb_tx_streams * sizeof(int32_t*)); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 19977b01e3..68066f8a86 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -265,7 +265,7 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) ue->nr_csi_info->csi_rs_generated_signal = malloc16(NR_MAX_CSI_PORTS * sizeof(*ue->nr_csi_info->csi_rs_generated_signal)); for (int i = 0; i < NR_MAX_CSI_PORTS; i++) { ue->nr_csi_info->csi_rs_generated_signal[i] = - malloc16_clear(fp->samples_per_frame_wCP * sizeof(**ue->nr_csi_info->csi_rs_generated_signal)); + malloc16_clear(fp->samples_per_slot_wCP * sizeof(**ue->nr_csi_info->csi_rs_generated_signal)); } ue->nr_srs_info = malloc16_clear(sizeof(nr_srs_info_t)); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 12bff45dee..edb296e8a4 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -53,7 +53,6 @@ static void nr_pdcch_scrambling(uint32_t *in, uint32_t size, uint32_t Nid, uint3 void nr_generate_dci(PHY_VARS_gNB *gNB, const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, - int txdataF_offset, NR_DL_FRAME_PARMS *frame_parms, int slot) { @@ -179,7 +178,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, /// Resource mapping uint16_t amp = gNB->TX_AMP; - c16_t *txdataF = gNB->common_vars.txdataF[beam_nb][0] + txdataF_offset; + c16_t *txdataF = gNB->common_vars.txdataF[beam_nb][0]; if (cset_start_sc >= frame_parms->ofdm_symbol_size) cset_start_sc -= frame_parms->ofdm_symbol_size; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.h b/openair1/PHY/NR_TRANSPORT/nr_dci.h index 57651f03a2..5a237ba80d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.h @@ -28,7 +28,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, - int txdataF_offset, NR_DL_FRAME_PARMS *frame_parms, int slot); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 24cf6b72b6..b09f816c7d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -645,7 +645,6 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC if (start_sc >= symbol_sz) start_sc -= symbol_sz; - const uint32_t txdataF_offset = slot * frame_parms->samples_per_slot_wCP; #ifdef DEBUG_DLSCH_MAPPING printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n", start_sc, @@ -756,7 +755,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC start_meas(&gNB->dlsch_precoding_stats); for (int ant = 0; ant < frame_parms->nb_antennas_tx; ant++) { - const size_t txdataF_offset_per_symbol = l_symbol * symbol_sz + txdataF_offset; + const size_t txdataF_offset_per_symbol = l_symbol * symbol_sz; do_txdataF(txdataF, symbol_sz, txdataF_precoding, gNB, rel15, ant, start_sc, txdataF_offset_per_symbol); } stop_meas(&gNB->dlsch_precoding_stats); diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 3004728091..566a382bfa 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -281,7 +281,6 @@ static int nr_csi_rs_channel_estimation( int16_t *log2_maxh, uint32_t *noise_power) { - const int dataF_offset = proc->nr_slot_rx * fp->samples_per_slot_wCP; *noise_power = 0; int maxh = 0; int count = 0; @@ -316,7 +315,7 @@ static int nr_csi_rs_channel_estimation( for (int lp = 0; lp <= csi_mapping->lprime; lp++) { uint16_t symb = lp + csi_mapping->loverline[cdm_id]; uint64_t symbol_offset = symb * fp->ofdm_symbol_size; - const c16_t *tx_csi_rs_signal = &csi_rs_generated_signal[port_tx][symbol_offset+dataF_offset]; + const c16_t *tx_csi_rs_signal = &csi_rs_generated_signal[port_tx][symbol_offset]; const c16_t *rx_csi_rs_signal = &csi_rs_received_signal[ant_rx][symbol_offset]; c16_t tmp = c16MulConjShift(tx_csi_rs_signal[k], rx_csi_rs_signal[k], nr_csi_info->csi_rs_generated_signal_bits); // This is not just the LS estimation for each (k,l), but also the sum of the different contributions diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c index 557214c63f..7cc14b385f 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c @@ -25,7 +25,6 @@ static void csi_rs_resource_mapping(c16_t **dataF, int csi_rs_length, int16_t mod_csi[][csi_rs_length >> 1], int ofdm_symbol_size, - int dataF_offset, int start_sc, const csi_mapping_parms_t *mapping_parms, int start_rb, @@ -66,7 +65,7 @@ static void csi_rs_resource_mapping(c16_t **dataF, else wt = -1; } - int index = (l * ofdm_symbol_size + k) + dataF_offset; + int index = (l * ofdm_symbol_size + k); dataF[p][index].r = (beta * wt * wf * mod_csi[l][mprime << 1]) >> 15; dataF[p][index].i = (beta * wt * wf * mod_csi[l][(mprime << 1) + 1]) >> 15; LOG_D(PHY, @@ -622,13 +621,10 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, // CDM group size from CDM type index const int gs = get_cdm_group_size(cdm_type); - const int dataF_offset = slot * frame_parms->samples_per_slot_wCP; - csi_rs_resource_mapping(dataF, frame_parms->N_RB_DL << 4, mod_csi, frame_parms->ofdm_symbol_size, - dataF_offset, frame_parms->first_carrier_offset, phy_csi_parms, start_rb, diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index ca712bbaf9..01b6fe7389 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -175,7 +175,6 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx) PHY_VARS_gNB *gNB = gNB_list[0]; nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; - int txdataF_offset = slot_tx * fp->samples_per_slot_wCP; start_meas(&ru->precoding_stats); if (gNB->common_vars.analog_bf) { @@ -195,8 +194,8 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx) for (int b = 0; b < ru->num_beams_period; b++) { for (int i = 0; i < Ptx; ++i) { int tx_idx = i + b * ru->nb_tx; - memcpy((void*)ru->common.txdataF_BF[tx_idx], - (void*)&gNB->common_vars.txdataF[b][i][txdataF_offset], + memcpy((void *)ru->common.txdataF_BF[tx_idx], + (void *)gNB->common_vars.txdataF[b][i], fp->samples_per_slot_wCP * sizeof(int32_t)); } } @@ -219,8 +218,7 @@ void nr_feptx(void *arg) NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; int numSymbols = feptx->numSymbols; int numSamples = feptx->numSymbols * fp->ofdm_symbol_size; - int txdataF_offset = (slot * fp->samples_per_slot_wCP) + startSymbol * fp->ofdm_symbol_size; - int txdataF_BF_offset = startSymbol * fp->ofdm_symbol_size; + int txdataF_offset = startSymbol * fp->ofdm_symbol_size; int tx_idx = aa + bb * ru->nb_tx; @@ -235,9 +233,9 @@ void nr_feptx(void *arg) // If there is no digital beamforming we just need to copy the data to RU if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) - memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset], - (void*)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset], - numSamples * sizeof(int32_t)); + memcpy((void *)&ru->common.txdataF_BF[tx_idx][txdataF_offset], + (void *)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset], + numSamples * sizeof(int32_t)); else { AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n"); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 4e69f8fa69..80f96e1f43 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -146,7 +146,6 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n", frame, slot, ssb_start_symbol); const nfapi_nr_tx_precoding_and_beamforming_t *pb = &pdu->precoding_and_beamforming; c16_t ***txdataF = gNB->common_vars.txdataF; - int txdataF_offset = slot * fp->samples_per_slot_wCP; // beam number in a scenario with multiple concurrent beams int bitmap = SL_to_bitmap(ssb_start_symbol, 4); // 4 ssb symbols int beam_nb = beam_index_allocation(gNB->enable_analog_das, @@ -156,15 +155,15 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n fp->symbols_per_slot, bitmap); - nr_generate_pss(&txdataF[beam_nb][0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp); - nr_generate_sss(&txdataF[beam_nb][0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp); + 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); uint16_t slots_per_hf = (fp->slots_per_frame) >> 1; int n_hf = slot < slots_per_hf ? 0 : 1; int hf = fp->Lmax == 4 ? n_hf : 0; nr_generate_pbch_dmrs(nr_gold_pbch(fp->Lmax, gNB->gNB_config.cell_config.phy_cell_id.value, hf, ssb_index & 7), - &txdataF[beam_nb][0][txdataF_offset], + txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, @@ -182,7 +181,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n nr_generate_pbch(gNB, ssb_pdu, - &txdataF[beam_nb][0][txdataF_offset], + txdataF[beam_nb][0], ssb_start_symbol, n_hf, frame, @@ -246,7 +245,6 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, { const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - const int txdataF_offset = slot * fp->samples_per_slot_wCP; if ((cfg->cell_config.frame_duplex_type.value == TDD) && (nr_slot_select(cfg,frame,slot) == NR_UPLINK_SLOT)) return; @@ -254,7 +252,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, // clear the transmit data array and beam index for the current slot for (int i = 0; i < gNB->common_vars.num_beams_period; i++) { for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) { - memset(&gNB->common_vars.txdataF[i][aa][txdataF_offset], 0, fp->samples_per_slot_wCP * sizeof(***gNB->common_vars.txdataF)); + memset(gNB->common_vars.txdataF[i][aa], 0, fp->samples_per_slot_wCP * sizeof(***gNB->common_vars.txdataF)); } } @@ -268,13 +266,13 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, { int slot_prs = (slot - i * prs_config->PRSResourceTimeGap + fp->slots_per_frame) % fp->slots_per_frame; LOG_D(PHY,"gNB_TX: frame %d, slot %d, slot_prs %d, PRS Resource ID %d\n",frame, slot, slot_prs, rsc_id); - nr_generate_prs(slot_prs, &gNB->common_vars.txdataF[0][0][txdataF_offset], AMP, prs_config, fp); + nr_generate_prs(slot_prs, gNB->common_vars.txdataF[0][0], AMP, prs_config, fp); } } } for (int i = 0; i < UL_dci_req->numPdus; ++i) - nr_generate_dci(gNB, &UL_dci_req->ul_dci_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot); + nr_generate_dci(gNB, &UL_dci_req->ul_dci_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15, &gNB->frame_parms, slot); int num_pdsch = 0; for (int i = 0; i < DL_req->dl_tti_request_body.nPDUs; ++i) { @@ -284,7 +282,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, nr_common_signal_procedures(gNB, frame, slot, &dl_tti_pdu->ssb_pdu); break; case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - nr_generate_dci(gNB, &dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot); + nr_generate_dci(gNB, &dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15, &gNB->frame_parms, slot); break; case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: nr_generate_csi_rs_gNB(gNB, slot, &dl_tti_pdu->csi_rs_pdu); @@ -321,7 +319,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) { if (gNB->phase_comp) { apply_nr_rotation_TX(fp, - &gNB->common_vars.txdataF[i][aa][txdataF_offset], + gNB->common_vars.txdataF[i][aa], fp->symbol_rotation[0], slot, fp->N_RB_DL, @@ -333,7 +331,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, T_INT(frame), T_INT(slot), T_INT(aa), - T_BUFFER(&gNB->common_vars.txdataF[i][aa][txdataF_offset], fp->samples_per_slot_wCP * sizeof(int32_t))); + T_BUFFER(gNB->common_vars.txdataF[i][aa], fp->samples_per_slot_wCP * sizeof(int32_t))); } } stop_meas(&gNB->phase_comp_stats); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b068936739..aa9ebccde8 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1123,29 +1123,27 @@ int main(int argc, char **argv) phy_procedures_gNB_TX(gNB, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req, frame, slot); stop_meas(&gNB->phy_proc_tx); - int txdataF_offset = slot * frame_parms->samples_per_slot_wCP; - if (n_trials==1) { LOG_M("txsigF0.m","txsF0=", - &gNB->common_vars.txdataF[0][0][txdataF_offset +2 * frame_parms->ofdm_symbol_size], + &gNB->common_vars.txdataF[0][0][2 * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); if (gNB->frame_parms.nb_antennas_tx>1) LOG_M("txsigF1.m","txsF1=", - &gNB->common_vars.txdataF[0][1][txdataF_offset + 2 * frame_parms->ofdm_symbol_size], + &gNB->common_vars.txdataF[0][1][2 * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); } if (n_trials == 1) - printf("slot_offset %d, txdataF_offset %d \n", slot_offset, txdataF_offset); + printf("slot_offset %d\n", slot_offset); //TODO: loop over slots for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { if (cyclic_prefix_type == 1) { - PHY_ofdm_mod((int *)&gNB->common_vars.txdataF[0][aa][txdataF_offset], + PHY_ofdm_mod((int *)gNB->common_vars.txdataF[0][aa], (int *)&txdata[aa][slot_offset], frame_parms->ofdm_symbol_size, 12, @@ -1156,7 +1154,7 @@ int main(int argc, char **argv) for (int i = 0; i < 14; i++) { was_symbol_used[i] = true; } - nr_normal_prefix_mod(&gNB->common_vars.txdataF[0][aa][txdataF_offset], + nr_normal_prefix_mod(gNB->common_vars.txdataF[0][aa], &txdata[aa][slot_offset], 14, frame_parms, diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 5702be2cf9..cad3012400 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -567,9 +567,9 @@ int main(int argc, char **argv) } } } - LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0][0],frame_length_complex_samples_no_prefix, 1, 1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[0][1],frame_length_complex_samples_no_prefix, 1, 1); + LOG_M("txsigF0.m", "txsF0", gNB->common_vars.txdataF[0][0], frame_parms->samples_per_slot_wCP, 1, 1); + if (gNB->frame_parms.nb_antennas_tx > 1) + LOG_M("txsigF1.m", "txsF1", gNB->common_vars.txdataF[0][1], frame_parms->samples_per_slot_wCP, 1, 1); } else { printf("Reading %d samples from file to antenna buffer %d\n",frame_length_complex_samples,0); From f8aeba44f485b08e1ccc5a4070c8912ab5e90046 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 15 Oct 2025 09:28:33 +0200 Subject: [PATCH 06/30] RLC status ind: make only one call per UE --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 25 +++++++------- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 26 ++++++++------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 33 +++++++++++-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 4 +-- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 18 ++++++---- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h | 2 +- 6 files changed, 62 insertions(+), 46 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index fcc977d9e5..51e69a76eb 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1452,23 +1452,24 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac, bool BSRsent) static void nr_update_rlc_buffers_status(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index) { + logical_chan_id_t ch[NR_MAX_NUM_LCID] = {0}; + int n = 0; for (int i = 0; i < mac->lc_ordered_list.count; i++) { nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; if (lc_info->rb_suspended) continue; - int lcid = lc_info->lcid; + ch[n++] = lc_info->lcid; + } + + mac_rlc_status_resp_t ret[NR_MAX_NUM_LCID] = {0}; + nr_mac_rlc_status_ind(mac->ue_id, frameP, n, ch, ret); + for (int i = 0; i < n; ++i) { + const logical_chan_id_t lcid = ch[i]; + const rlc_buffer_occupancy_t b = ret[i].bytes_in_buffer; NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid); - mac_rlc_status_resp_t rlc_status = nr_mac_rlc_status_ind(mac->ue_id, frameP, lcid); - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(NR_MAC, - "[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n", - mac->ue_id, - lcid, - rlc_status.bytes_in_buffer, - frameP, - slotP); - } - lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer; + if (b > 0) + LOG_D(NR_MAC, "[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n", mac->ue_id, lcid, b, frameP, slotP); + lc_sched_info->LCID_buffer_remain = b; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 1657a492fe..d2c6250070 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1701,21 +1701,23 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ int current_harq_pid = sched_ctrl->retrans_dl_harq.head; - logical_chan_id_t lcid = DL_SCH_LCID_CCCH; + logical_chan_id_t lcid = 0; if (current_harq_pid < 0) { - // Check for data on SRB0 (RRCSetup) - mac_rlc_status_resp_t srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); + const logical_chan_id_t lcid_l[2] = {DL_SCH_LCID_CCCH, DL_SCH_LCID_DCCH}; + mac_rlc_status_resp_t stat[2]; + nr_mac_rlc_status_ind(UE->rnti, frameP, 2, lcid_l, stat); - if (srb_status.bytes_in_buffer == 0) { - lcid = DL_SCH_LCID_DCCH; - // Check for data on SRB1 (RRCReestablishment, RRCReconfiguration) - srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); + if (stat[0].bytes_in_buffer > 0) { + // some data in SRB0 (likely RRCSetup) + mac_sdu_length = stat[0].bytes_in_buffer; + lcid = lcid_l[0]; + } else if (stat[1].bytes_in_buffer > 0) { + // some data in SRB1 (likely RRCReestablishmnt/RRCReconfiguration) + mac_sdu_length = stat[1].bytes_in_buffer; + lcid = lcid_l[1]; + } else { + return; // no data to forward } - - // Need to wait until data for Msg4 is ready - if (srb_status.bytes_in_buffer == 0) - return; - mac_sdu_length = srb_status.bytes_in_buffer; } const int n_slots_frame = nr_mac->frame_structure.numb_slots_frame; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 921003d110..075e46dd52 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -326,31 +326,38 @@ static uint32_t update_dlsch_buffer(frame_t frame, slot_t slot, NR_UE_info_t *UE sched_ctrl->num_total_bytes = 0; sched_ctrl->dl_pdus_total = 0; + logical_chan_id_t ch[NR_MAX_NUM_LCID] = {0}; + int n = 0; /* loop over all activated logical channels */ - for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); ++i) { - const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); - const int lcid = c->lcid; - const uint16_t rnti = UE->rnti; - LOG_D(NR_MAC, "UE %x: LCID %d\n", rnti, lcid); - memset(&sched_ctrl->rlc_status[lcid], 0, sizeof(sched_ctrl->rlc_status[lcid])); - if (c->suspended) + FOR_EACH_SEQ_ARR(const nr_lc_config_t *, c, &sched_ctrl->lc_config ) { + logical_chan_id_t lcid = c->lcid; + if (c->suspended || (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt))) { + memset(&sched_ctrl->rlc_status[lcid], 0, sizeof(sched_ctrl->rlc_status[lcid])); continue; - if (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt)) - continue; - sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid); + } + ch[n++] = lcid; + } - if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) + mac_rlc_status_resp_t ret[NR_MAX_NUM_LCID] = {0}; + nr_mac_rlc_status_ind(UE->rnti, frame, n, ch, ret); + + for (int i = 0; i < n; ++i) { + logical_chan_id_t lcid = ch[i]; + + if (ret[i].bytes_in_buffer == 0) continue; + sched_ctrl->rlc_status[lcid] = ret[i]; sched_ctrl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer; sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; LOG_D(MAC, - "%4d.%2d UE %04x LCID %d status: %d bytes, total buffer %d bytes %d PDUs\n", + "%4d.%2d UE %04x LCID %d status: %d bytes, %d PDUs, total buffer %d bytes %d PDUs\n", frame, slot, UE->rnti, lcid, - sched_ctrl->rlc_status[lcid].bytes_in_buffer, + ret[i].bytes_in_buffer, + ret[i].pdus_in_buffer, sched_ctrl->num_total_bytes, sched_ctrl->dl_pdus_total); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index f23dfe8b30..d78ae9280f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -144,11 +144,11 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) sched_ctrl->num_total_bytes = 0; DevAssert(seq_arr_size(&sched_ctrl->lc_config) == 1); const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, 0); - const int lcid = c->lcid; + const logical_chan_id_t lcid = c->lcid; const uint16_t rnti = UE->rnti; /* update sched_ctrl->num_total_bytes so that postprocessor schedules data, * if available */ - sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid); + nr_mac_rlc_status_ind(rnti, frame, 1, &lcid, &sched_ctrl->rlc_status[lcid]); sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; int CCEIndex = get_cce_index(mac, diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 126f9fb51c..4597b96478 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -223,12 +223,10 @@ tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, return ret; } -mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t frame, const logical_chan_id_t channel_idP) +static mac_rlc_status_resp_t _nr_rlc_status_ind(nr_rlc_ue_t *ue, frame_t frame, logical_chan_id_t channel_idP) { mac_rlc_status_resp_t ret; - nr_rlc_manager_lock(nr_rlc_ue_manager); - nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, channel_idP); if (rb != NULL) { @@ -243,12 +241,10 @@ mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t ret.bytes_in_buffer = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size; } else { if (!(frame % 128) || channel_idP == 0) //to suppress this warning message - LOG_W(RLC, "Radio Bearer (channel ID %d) is NULL for UE %d\n", channel_idP, ue_id); + LOG_W(RLC, "Radio Bearer (channel ID %d) is NULL for UE %d\n", channel_idP, ue->ue_id); ret.bytes_in_buffer = 0; } - nr_rlc_manager_unlock(nr_rlc_ue_manager); - ret.pdus_in_buffer = 0; /* TODO: creation time may be important (unit: frame, as it seems) */ ret.head_sdu_creation_time = 0; @@ -257,6 +253,16 @@ mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t return ret; } +void nr_mac_rlc_status_ind(uint16_t ue_id, frame_t frame, int n_ch, const logical_chan_id_t *ch, mac_rlc_status_resp_t *ret) +{ + nr_rlc_manager_lock(nr_rlc_ue_manager); + nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); + for (int i = 0; i < n_ch; ++i) { + ret[i] = _nr_rlc_status_ind(ue, frame, ch[i]); + } + nr_rlc_manager_unlock(nr_rlc_ue_manager); +} + rlc_op_status_t nr_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP, diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index 454a59b928..c426aa8d6e 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -59,7 +59,7 @@ rlc_op_status_t nr_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, const mui_t muiP, sdu_size_t sdu_sizeP, uint8_t *sdu_pP); -mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t frame, const logical_chan_id_t channel_idP); +void nr_mac_rlc_status_ind(uint16_t ue_id, frame_t frame, int n_ch, const logical_chan_id_t *ch, mac_rlc_status_resp_t *ret); void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig); void nr_rlc_add_drb(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig); From d0a6be27daa618efcc0bc0b917ae3d42887ed4b4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Jan 2026 08:15:29 +0100 Subject: [PATCH 07/30] RLC data ind: change API to handle multiple TB, but use only one --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 6 +++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 9 ++++--- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 27 ++++++++++--------- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h | 10 ++++--- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 672bc3c3a2..ffe1c99823 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3971,7 +3971,8 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ if (mac_len > 0) { LOG_DDUMP(NR_MAC, (void *)pduP, mac_subheader_len + mac_len, LOG_DUMP_CHAR, "DL_SCH_LCID_CCCH (e.g. RRCSetup) payload: "); - nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = rx_lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, &ind, 1); } break; case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH: @@ -4091,7 +4092,8 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ break; } LOG_D(NR_MAC, "%4d.%2d : DLSCH -> LCID %d %d bytes\n", frameP, slot, rx_lcid, mac_len); - nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = rx_lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, &ind, 1); break; default: LOG_W(MAC, "unknown lcid %02x\n", rx_lcid); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 3282c4a483..ca46f52e9a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -456,7 +456,8 @@ static int nr_process_mac_pdu(instance_t module_idP, } if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) { - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, 0, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = 0, .buf = pduP + mac_subheader_len, .len = mac_len}; + nr_mac_rlc_data_ind(module_idP, UE->rnti, true, &ind, 1); } else { LOG_E(NR_MAC, "prepare_initial_ul_rrc_message() returned false, cannot forward CCCH message\n"); } @@ -475,7 +476,8 @@ static int nr_process_mac_pdu(instance_t module_idP, if (!srbc || srbc->suspended) { LOG_I(NR_MAC, "RNTI %04x LCID %d: ignoring %d bytes\n", UE->rnti, lcid, mac_len); } else { - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + nr_mac_rlc_data_ind(module_idP, UE->rnti, true, &ind, 1); UE->mac_stats.ul.total_sdu_bytes += mac_len; UE->mac_stats.ul.lc_bytes[lcid] += mac_len; @@ -499,7 +501,8 @@ static int nr_process_mac_pdu(instance_t module_idP, } else { UE->mac_stats.ul.lc_bytes[lcid] += mac_len; - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + nr_mac_rlc_data_ind(module_idP, UE->rnti, true, &ind, 1); sdus += 1; /* Updated estimated buffer when receiving data */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 4597b96478..9710df661e 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -163,12 +163,12 @@ void nr_rlc_release_entity(int ue_id, logical_chan_id_t channel_id) void nr_mac_rlc_data_ind(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, - const logical_chan_id_t channel_idP, - char *buffer_pP, - const tb_size_t tb_sizeP) + const nr_rlc_data_ind_t *data, + int num_data) { if (gnb_flagP) - T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(ue_id), T_INT(channel_idP), T_INT(tb_sizeP)); + for (int i = 0; i < num_data; ++i) + T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(ue_id), T_INT(data[i].ch), T_INT(data[i].len)); nr_rlc_manager_lock(nr_rlc_ue_manager); nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); @@ -176,15 +176,16 @@ void nr_mac_rlc_data_ind(const module_id_t module_idP, if(ue == NULL) LOG_I(RLC, "RLC instance for the given UE was not found \n"); - nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, channel_idP); - - if (rb != NULL) { - LOG_D(RLC, "RB found! (channel ID %d) \n", channel_idP); - rb->set_time(rb, get_nr_rlc_current_time()); - rb->recv_pdu(rb, buffer_pP, tb_sizeP); - } else { - LOG_E(RLC, "Fatal: no RB found (channel ID %d UE ID %d)\n", channel_idP, ue_id); - // exit(1); + for (int i = 0; i < num_data; ++i) { + logical_chan_id_t ch = data[i].ch; + nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, ch); + if (rb != NULL) { + LOG_D(RLC, "RB found! (channel ID %d) \n", ch); + rb->set_time(rb, get_nr_rlc_current_time()); + rb->recv_pdu(rb, (char *)data[i].buf, data[i].len); + } else { + LOG_W(RLC, "no RB found (channel ID %d UE ID %d)\n", ch, ue_id); + } } nr_rlc_manager_unlock(nr_rlc_ue_manager); diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index c426aa8d6e..93759ef161 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -41,12 +41,16 @@ struct NR_RLC_Config; struct NR_LogicalChannelConfig; int nr_rlc_module_init(nr_rlc_op_mode_t mode); +typedef struct nr_rlc_data_ind { + logical_chan_id_t ch; + uint8_t *buf; + tb_size_t len; +} nr_rlc_data_ind_t; void nr_mac_rlc_data_ind(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, - const logical_chan_id_t channel_idP, - char *buffer_pP, - const tb_size_t tb_sizeP); + const nr_rlc_data_ind_t *data, + int num_data); tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, From 0b100620f4355a4a92830b7350ded5bd8a63ce9a Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Thu, 28 Nov 2024 19:45:51 +0100 Subject: [PATCH 08/30] Changed uplink_frequency_offset from int32 to int64, required for NTN-FR2 --- executables/lte-softmodem.c | 2 +- executables/lte-softmodem.h | 2 +- executables/lte-ue.c | 13 ++++++++----- executables/lte-uesoftmodem.c | 2 +- executables/main_nr_ru.c | 2 +- executables/main_ru.c | 2 +- executables/nr-cuup.c | 2 +- executables/nr-softmodem.c | 2 +- executables/nr-uesoftmodem.c | 2 +- executables/softmodem-common.h | 6 +++--- openair1/PHY/TOOLS/calibration_test.c | 2 +- openair1/SIMULATION/NR_PHY/dlschsim.c | 2 +- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/pbchsim.c | 2 +- openair1/SIMULATION/NR_PHY/prachsim.c | 2 +- openair1/SIMULATION/NR_PHY/psbchsim.c | 2 +- openair1/SIMULATION/NR_PHY/pucchsim.c | 2 +- openair1/SIMULATION/NR_PHY/srssim.c | 2 +- openair1/SIMULATION/NR_PHY/ulschsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- tests/nr-cu-nrppa/nr-cu-nrppa.c | 2 +- 21 files changed, 30 insertions(+), 27 deletions(-) diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index e2c4144707..0c9fb0884d 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -101,7 +101,7 @@ int oai_exit = 0; int NB_UE_INST = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; int UE_scan = 1; int UE_scan_carrier = 0; diff --git a/executables/lte-softmodem.h b/executables/lte-softmodem.h index 6642141526..0d05c9ba9d 100644 --- a/executables/lte-softmodem.h +++ b/executables/lte-softmodem.h @@ -114,7 +114,7 @@ extern uint16_t ue_id_g; extern uint16_t node_number; extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; -extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +extern int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern int rx_input_level_dBm; extern openair0_config_t openair0_cfg[MAX_CARDS]; diff --git a/executables/lte-ue.c b/executables/lte-ue.c index 1a187ad51f..8cbf9b903f 100644 --- a/executables/lte-ue.c +++ b/executables/lte-ue.c @@ -437,8 +437,10 @@ static void *UE_thread_synch(void *arg) { printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min); if ((eutra_bands[ind].dl_min <= UE->frame_parms.dl_CarrierFreq) && (eutra_bands[ind].dl_max >= UE->frame_parms.dl_CarrierFreq)) { - for (i=0; i<4; i++) - uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min; + for (i=0; i<4; i++) { + int32_t delta = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min; + uplink_frequency_offset[CC_id][i] = delta; + } found = 1; break; @@ -473,8 +475,8 @@ static void *UE_thread_synch(void *arg) { for (i=0; irf_map.card].rx_num_channels; i++) { downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min; - uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = - bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min; + int32_t delta = bands_to_scan.band_info[CC_id].ul_min - bands_to_scan.band_info[CC_id].dl_min; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = delta; openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; @@ -517,7 +519,8 @@ static void *UE_thread_synch(void *arg) { for (i=0; irf_map.card].rx_num_channels; i++) { downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset; - uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset; + int32_t delta = bands_to_scan.band_info[current_band].ul_min - bands_to_scan.band_info[0].dl_min + current_offset; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = delta; openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index 322fecae98..030db0b72f 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -92,7 +92,7 @@ unsigned int mmapped_dma=0; UE_MAC_INST *UE_mac_inst = NULL; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; diff --git a/executables/main_nr_ru.c b/executables/main_nr_ru.c index 1aab4e95f6..352102498e 100644 --- a/executables/main_nr_ru.c +++ b/executables/main_nr_ru.c @@ -55,7 +55,7 @@ extern void set_function_spec_param(RU_t *ru); extern void start_NR_RU(); extern void init_NR_RU(configmodule_interface_t *cfg, char *); -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; void nfapi_setmode(nfapi_mode_t nfapi_mode) { diff --git a/executables/main_ru.c b/executables/main_ru.c index 3579c26f7a..6cd48d9b13 100644 --- a/executables/main_ru.c +++ b/executables/main_ru.c @@ -84,7 +84,7 @@ extern void init_RU_proc(RU_t *ru); extern void kill_RU_proc(RU_t *ru); extern void set_function_spec_param(RU_t *ru); -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; void nfapi_setmode(nfapi_mode_t nfapi_mode) { return; } diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index df2f633d95..661059afaa 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -36,7 +36,7 @@ RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; int oai_exit = 0; instance_t CUuniqInstance = 0; diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 938bbeee88..25177bbfc7 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -101,7 +101,7 @@ int oai_exit = 0; unsigned int mmapped_dma=0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; char *uecap_file; runmode_t mode = normal_txrx; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index df4088a87d..633cc80b3a 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -103,7 +103,7 @@ RAN_CONTEXT_t RC; int oai_exit = 0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t sidelink_frequency[MAX_NUM_CCs][4]; // UE and OAI config variables diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 1018716bb7..ee737310c9 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -138,8 +138,8 @@ extern int usrp_tx_thread; {"clock-source", CONFIG_HLP_CLK, 0, .uptr=&CLOCK_SOURCE, .defintval=0, TYPE_UINT, 0}, \ {"time-source", CONFIG_HLP_TME, 0, .uptr=&TIMING_SOURCE, .defintval=0, TYPE_UINT, 0}, \ {"tune-offset", CONFIG_HLP_TUNE_OFFSET, 0, .dblptr=&TUNE_OFFSET, .defintval=0, TYPE_DOUBLE, 0}, \ - {"C" , CONFIG_HLP_DLF, 0, .u64ptr=&(downlink_frequency[0][0]), .defint64val=0, TYPE_UINT64, 0}, \ - {"CO" , CONFIG_HLP_ULF, 0, .iptr=&(uplink_frequency_offset[0][0]), .defintval=0, TYPE_INT, 0}, \ + {"C" , CONFIG_HLP_DLF, 0, .u64ptr=&(downlink_frequency[0][0]), .defuintval=0, TYPE_UINT64, 0}, \ + {"CO" , CONFIG_HLP_ULF, 0, .i64ptr=&(uplink_frequency_offset[0][0]), .defintval=0, TYPE_INT64, 0}, \ {"a" , CONFIG_HLP_CHOFF, 0, .iptr=&CHAIN_OFFSET, .defintval=0, TYPE_INT, 0}, \ {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, .uptr=&do_forms, .defintval=0, TYPE_UINT, 0}, \ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, .iptr=&cpu_meas_enabled, .defintval=0, TYPE_INT, 0}, \ @@ -330,7 +330,7 @@ char *get_softmodem_function(void); #define SOFTMODEM_RTSIGNAL (SIGRTMIN+1) void set_softmodem_sighandler(void); extern uint64_t downlink_frequency[MAX_NUM_CCs][4]; -extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +extern int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; extern int usrp_tx_thread; extern int sf_ahead; extern int oai_exit; diff --git a/openair1/PHY/TOOLS/calibration_test.c b/openair1/PHY/TOOLS/calibration_test.c index 05420672ad..0f5a76183e 100644 --- a/openair1/PHY/TOOLS/calibration_test.c +++ b/openair1/PHY/TOOLS/calibration_test.c @@ -11,7 +11,7 @@ unsigned int mmapped_dma=0; uint32_t timing_advance; int8_t threequarter_fs; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; int cpu_meas_enabled; THREAD_STRUCT thread_struct; uint32_t target_ul_mcs = 9; diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 6f4282f130..7e45cdd9b6 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -56,7 +56,7 @@ PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; UE_nr_rxtx_proc_t proc; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t downlink_frequency[MAX_NUM_CCs][4]; double cpuf; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index b068936739..73d22650a8 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -104,7 +104,7 @@ const char *__asan_default_options() PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; char *uecap_file; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 5702be2cf9..9348d5d32b 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -55,7 +55,7 @@ PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 7966c74375..6f6d7c1102 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -79,7 +79,7 @@ RU_t *ru; double cpuf; //uint8_t nfapi_mode=0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint32_t N_RB_DL = 106; NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); } diff --git a/openair1/SIMULATION/NR_PHY/psbchsim.c b/openair1/SIMULATION/NR_PHY/psbchsim.c index cb78915cbb..6b6784fca9 100644 --- a/openair1/SIMULATION/NR_PHY/psbchsim.c +++ b/openair1/SIMULATION/NR_PHY/psbchsim.c @@ -71,7 +71,7 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu, uint8_t *nb_dmrs_re_per } uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; THREAD_STRUCT thread_struct; instance_t DUuniqInstance = 0; instance_t CUuniqInstance = 0; diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index bfa294a55f..9ddd76e038 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -53,7 +53,7 @@ THREAD_STRUCT thread_struct; PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t downlink_frequency[MAX_NUM_CCs][4]; double cpuf; diff --git a/openair1/SIMULATION/NR_PHY/srssim.c b/openair1/SIMULATION/NR_PHY/srssim.c index d68f925374..57c239899f 100644 --- a/openair1/SIMULATION/NR_PHY/srssim.c +++ b/openair1/SIMULATION/NR_PHY/srssim.c @@ -48,7 +48,7 @@ PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; char *uecap_file = NULL; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; uint64_t downlink_frequency[MAX_NUM_CCs][4]; diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index d15deb4277..93aae9c1d6 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -55,7 +55,7 @@ THREAD_STRUCT thread_struct; PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t downlink_frequency[MAX_NUM_CCs][4]; static softmodem_params_t softmodem_params; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index da6b901a11..fa8643023f 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -106,7 +106,7 @@ PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; char *uecap_file; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; double cpuf; //uint8_t nfapi_mode = 0; diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c index de784a3a16..ee8156343f 100644 --- a/tests/nr-cu-nrppa/nr-cu-nrppa.c +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -37,7 +37,7 @@ RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; uint64_t downlink_frequency[MAX_NUM_CCs][4]; -int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int64_t uplink_frequency_offset[MAX_NUM_CCs][4]; int oai_exit = 0; int gnb_id; int NB_UE_INST = 1; From 6c5a8aa1fc74159b52e8a51a7b75370150656d44 Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Tue, 3 Mar 2026 17:10:35 +0100 Subject: [PATCH 09/30] Added NTN-FR2 FDD bands defined in release 18. Bandtable modified. NTN-FR2 bands 510, 511, 512 added. TS 38.101-5 v 18.9 defines these 3 FR2-FDD bands for NTN operation. These bands are defined in Ka band range (17.3Ghz - 31Ghz) UL STEPSIZE, UL NOFFS added into band table --- common/utils/nr/nr_common.c | 247 +++++++++--------- common/utils/nr/nr_common.h | 6 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 4 +- 3 files changed, 129 insertions(+), 128 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 5fc6a8c1a9..4ed820c03f 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -178,92 +178,97 @@ uint8_t set_ssb_case(int scs, int nr_band) return ssb_case; } -// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) (Rel.17) +// Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) (Rel.18) // Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101) // Notes: -// - N_OFFs for bands from 80 to 89 and band 95 is referred to UL // - Frequencies are expressed in KHz -// - col: NR_band ul_min ul_max dl_min dl_max step N_OFFs_DL deltaf_raster -const nr_bandentry_t nr_bandtable[] = {{1, 1920000, 1980000, 2110000, 2170000, 20, 422000, 100}, - {2, 1850000, 1910000, 1930000, 1990000, 20, 386000, 100}, - {3, 1710000, 1785000, 1805000, 1880000, 20, 361000, 100}, - {5, 824000, 849000, 869000, 894000, 20, 173800, 100}, - {7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100}, - {8, 880000, 915000, 925000, 960000, 20, 185000, 100}, - {12, 699000, 716000, 729000, 746000, 20, 145800, 100}, - {13, 777000, 787000, 746000, 756000, 20, 149200, 100}, - {14, 788000, 798000, 758000, 768000, 20, 151600, 100}, - {18, 815000, 830000, 860000, 875000, 20, 172000, 100}, - {20, 832000, 862000, 791000, 821000, 20, 158200, 100}, - {24, 1627500, 1656500, 1526000, 1536000, 20, 305000, 100}, - {25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100}, - {26, 814000, 849000, 859000, 894000, 20, 171800, 100}, - {28, 703000, 758000, 758000, 813000, 20, 151600, 100}, - {29, 000, 000, 717000, 728000, 20, 143400, 100}, - {30, 2305000, 2315000, 2350000, 2360000, 20, 470000, 100}, - {34, 2010000, 2025000, 2010000, 2025000, 20, 402000, 100}, - {38, 2570000, 2620000, 2570000, 2630000, 20, 514000, 100}, - {39, 1880000, 1920000, 1880000, 1920000, 20, 376000, 100}, - {40, 2300000, 2400000, 2300000, 2400000, 20, 460000, 100}, - {41, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {41, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {46, 5150000, 5925000, 5150000, 5925000, 1, 743334, 15}, - {47, 5855000, 5925000, 5855000, 5925000, 1, 790334, 15}, - {48, 3550000, 3700000, 3550000, 3700000, 1, 636667, 15}, - {48, 3550000, 3700000, 3550000, 3700000, 2, 636668, 30}, - {50, 1432000, 1517000, 1432000, 1517000, 20, 286400, 100}, - {51, 1427000, 1432000, 1427000, 1432000, 20, 285400, 100}, - {53, 2483500, 2495000, 2483500, 2495000, 20, 496700, 100}, - {65, 1920000, 2010000, 2110000, 2200000, 20, 422000, 100}, - {66, 1710000, 1780000, 2110000, 2200000, 20, 422000, 100}, - {67, 000, 000, 738000, 758000, 20, 147600, 100}, - {70, 1695000, 1710000, 1995000, 2020000, 20, 399000, 100}, - {71, 663000, 698000, 617000, 652000, 20, 123400, 100}, - {74, 1427000, 1470000, 1475000, 1518000, 20, 295000, 100}, - {75, 000, 000, 1432000, 1517000, 20, 286400, 100}, - {76, 000, 000, 1427000, 1432000, 20, 285400, 100}, - {77, 3300000, 4200000, 3300000, 4200000, 1, 620000, 15}, - {77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30}, - {78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15}, - {78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30}, - {79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15}, - {79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30}, - {80, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {81, 880000, 915000, 000, 000, 20, 176000, 100}, - {82, 832000, 862000, 000, 000, 20, 166400, 100}, - {83, 703000, 748000, 000, 000, 20, 140600, 100}, - {84, 1920000, 1980000, 000, 000, 20, 384000, 100}, - {85, 698000, 716000, 728000, 746000, 20, 145600, 100}, - {86, 1710000, 1785000, 000, 000, 20, 342000, 100}, - {89, 824000, 849000, 000, 000, 20, 342000, 100}, - {90, 2496000, 2690000, 2496000, 2690000, 3, 499200, 15}, - {90, 2496000, 2690000, 2496000, 2690000, 6, 499200, 30}, - {90, 2496000, 2690000, 2496000, 2690000, 20, 499200, 100}, - {91, 832000, 862000, 1427000, 1432000, 20, 285400, 100}, - {92, 832000, 862000, 1432000, 1517000, 20, 286400, 100}, - {93, 880000, 915000, 1427000, 1432000, 20, 285400, 100}, - {94, 880000, 915000, 1432000, 1517000, 20, 286400, 100}, - {95, 2010000, 2025000, 000, 000, 20, 402000, 100}, - {96, 5925000, 7125000, 5925000, 7125000, 1, 795000, 15}, - {100, 874400, 880000, 919400, 925000, 20, 174880, 100}, - {101, 1900000, 1910000, 1900000, 1910000, 20, 380000, 100}, - {102, 5925000, 6425000, 5925000, 6425000, 1, 795000, 15}, - {104, 6425000, 7125000, 6425000, 7125000, 1, 828334, 15}, - {104, 6425000, 7125000, 6425000, 7125000, 2, 828334, 30}, - {254, 1610000, 1626500, 2483500, 2500000, 20, 496700, 100}, - {254, 1610000, 1626500, 2483500, 2500000, 2, 496700, 10}, - {255, 1626500, 1660500, 1525000, 1559000, 20, 305000, 100}, - {255, 1626500, 1660500, 1525000, 1559000, 2, 305000, 10}, - {256, 1980000, 2010000, 2170000, 2200000, 20, 434000, 100}, - {256, 1980000, 2010000, 2170000, 2200000, 2, 434000, 10}, - {257, 26500020, 29500000, 26500020, 29500000, 1, 2054166, 60}, - {257, 26500080, 29500000, 26500080, 29500000, 2, 2054167, 120}, - {258, 24250080, 27500000, 24250080, 27500000, 1, 2016667, 60}, - {258, 24250080, 27500000, 24250080, 27500000, 2, 2016667, 120}, - {260, 37000020, 40000000, 37000020, 40000000, 1, 2229166, 60}, - {260, 37000080, 40000000, 37000080, 40000000, 2, 2229167, 120}, - {261, 27500040, 28350000, 27500040, 28350000, 1, 2070833, 60}, - {261, 27500040, 28350000, 27500040, 28350000, 2, 2070833, 120}}; +// - col: NR_band ul_min ul_max dl_min dl_max ul_stepsize dl_stepsize N_OFFs_UL N_OFFs_DL deltaf_raster +const nr_bandentry_t nr_bandtable[] = {{1, 1920000, 1980000, 2110000, 2170000, 20, 20, 384000, 422000, 100}, + {2, 1850000, 1910000, 1930000, 1990000, 20, 20, 370000, 386000, 100}, + {3, 1710000, 1785000, 1805000, 1880000, 20, 20, 342000, 361000, 100}, + {5, 824000, 849000, 869000, 894000, 20, 20, 164800, 173800, 100}, + {7, 2500000, 2570000, 2620000, 2690000, 20, 20, 500000, 524000, 100}, + {8, 880000, 915000, 925000, 960000, 20, 20, 176000, 185000, 100}, + {12, 699000, 716000, 729000, 746000, 20, 20, 139800, 145800, 100}, + {13, 777000, 787000, 746000, 756000, 20, 20, 155400, 149200, 100}, + {14, 788000, 798000, 758000, 768000, 20, 20, 157600, 151600, 100}, + {18, 815000, 830000, 860000, 875000, 20, 20, 163000, 172000, 100}, + {20, 832000, 862000, 791000, 821000, 20, 20, 166400, 158200, 100}, + {24, 1626500, 1660500, 1525000, 1559000, 20, 20, 325300, 305000, 100}, + {25, 1850000, 1915000, 1930000, 1995000, 20, 20, 370000, 386000, 100}, + {26, 814000, 849000, 859000, 894000, 20, 20, 162800, 171800, 100}, + {28, 703000, 748000, 758000, 803000, 20, 20, 140600, 151600, 100}, + {29, 000, 000, 717000, 728000, 0, 20, 0, 143400, 100}, + {30, 2305000, 2315000, 2350000, 2360000, 20, 20, 461000, 470000, 100}, + {34, 2010000, 2025000, 2010000, 2025000, 20, 20, 402000, 402000, 100}, + {38, 2570000, 2620000, 2570000, 2620000, 20, 20, 514000, 514000, 100}, + {39, 1880000, 1920000, 1880000, 1920000, 20, 20, 376000, 376000, 100}, + {40, 2300000, 2400000, 2300000, 2400000, 20, 20, 460000, 460000, 100}, + {41, 2496000, 2690000, 2496000, 2690000, 3, 3, 499200, 499200, 15}, + {41, 2496000, 2690000, 2496000, 2690000, 6, 6, 499200, 499200, 30}, + {46, 5150000, 5925000, 5150000, 5925000, 1, 1, 743334, 743334, 15}, + {47, 5855000, 5925000, 5855000, 5925000, 1, 1, 790334, 790334, 15}, + {48, 3550000, 3700000, 3550000, 3700000, 1, 1, 636667, 636667, 15}, + {48, 3550000, 3700000, 3550000, 3700000, 2, 2, 636668, 636668, 30}, + {50, 1432000, 1517000, 1432000, 1517000, 20, 20, 286400, 286400, 100}, + {51, 1427000, 1432000, 1427000, 1432000, 20, 20, 285400, 285400, 100}, + {53, 2483500, 2495000, 2483500, 2495000, 20, 20, 496700, 496700, 100}, + {65, 1920000, 2010000, 2110000, 2200000, 20, 20, 384000, 422000, 100}, + {66, 1710000, 1780000, 2110000, 2200000, 20, 20, 342000, 422000, 100}, + {67, 000, 000, 738000, 758000, 0, 20, 0, 147600, 100}, + {70, 1695000, 1710000, 1995000, 2020000, 20, 20, 339000, 399000, 100}, + {71, 663000, 698000, 617000, 652000, 20, 20, 132600, 123400, 100}, + {74, 1427000, 1470000, 1475000, 1518000, 20, 20, 285400, 295000, 100}, + {75, 000, 000, 1432000, 1517000, 0, 20, 0, 286400, 100}, + {76, 000, 000, 1427000, 1432000, 0, 20, 0, 285400, 100}, + {77, 3300000, 4200000, 3300000, 4200000, 1, 1, 620000, 620000, 15}, + {77, 3300000, 4200000, 3300000, 4200000, 2, 2, 620000, 620000, 30}, + {78, 3300000, 3800000, 3300000, 3800000, 1, 1, 620000, 620000, 15}, + {78, 3300000, 3800000, 3300000, 3800000, 2, 2, 620000, 620000, 30}, + {79, 4400000, 5000000, 4400000, 5000000, 1, 1, 693334, 693334, 15}, + {79, 4400000, 5000000, 4400000, 5000000, 2, 2, 693334, 693334, 30}, + {80, 1710000, 1785000, 000, 000, 20, 0, 342000, 0, 100}, + {81, 880000, 915000, 000, 000, 20, 0, 176000, 0, 100}, + {82, 832000, 862000, 000, 000, 20, 0, 166400, 0, 100}, + {83, 703000, 748000, 000, 000, 20, 0, 140600, 0, 100}, + {84, 1920000, 1980000, 000, 000, 20, 0, 384000, 0, 100}, + {85, 698000, 716000, 728000, 746000, 20, 20, 139600, 145600, 100}, + {86, 1710000, 1780000, 000, 000, 20, 0, 342000, 0, 100}, + {89, 824000, 849000, 000, 000, 20, 0, 342000, 0, 100}, + {90, 2496000, 2690000, 2496000, 2690000, 3, 3, 499200, 499200, 15}, + {90, 2496000, 2690000, 2496000, 2690000, 6, 6, 499200, 499200, 30}, + {90, 2496000, 2690000, 2496000, 2690000, 20, 20, 499200, 499200, 100}, + {91, 832000, 862000, 1427000, 1432000, 20, 20, 166400, 285400, 100}, + {92, 832000, 862000, 1432000, 1517000, 20, 20, 166400, 286400, 100}, + {93, 880000, 915000, 1427000, 1432000, 20, 20, 176000, 285400, 100}, + {94, 880000, 915000, 1432000, 1517000, 20, 20, 176000, 286400, 100}, + {95, 2010000, 2025000, 000, 000, 20, 20, 402000, 402000, 100}, + {96, 5925000, 7125000, 5925000, 7125000, 1, 1, 795000, 795000, 15}, + {100, 874400, 880000, 919400, 925000, 20, 20, 174880, 174880, 100}, + {101, 1900000, 1910000, 1900000, 1910000, 20, 20, 380000, 380000, 100}, + {102, 5925000, 6425000, 5925000, 6425000, 1, 1, 795000, 795000, 15}, + {104, 6425000, 7125000, 6425000, 7125000, 1, 1, 828334, 828334, 15}, + {104, 6425000, 7125000, 6425000, 7125000, 2, 2, 828334, 828334, 30}, + {254, 1610000, 1626500, 2483500, 2500000, 20, 20, 322000, 496700, 100}, + {254, 1610000, 1626500, 2483500, 2500000, 2, 2, 322000, 496700, 10}, + {255, 1626500, 1660500, 1525000, 1559000, 20, 20, 325300, 305000, 100}, + {255, 1626500, 1660500, 1525000, 1559000, 2, 2, 325300, 305000, 10}, + {256, 1980000, 2010000, 2170000, 2200000, 20, 20, 396000, 434000, 100}, + {256, 1980000, 2010000, 2170000, 2200000, 2, 2, 396000, 434000, 10}, + {257, 26500020, 29500000, 26500020, 29500000, 1, 1, 2054166, 2054166, 60}, + {257, 26500080, 29500000, 26500080, 29500000, 2, 2, 2054167, 2054167, 120}, + {258, 24250080, 27500000, 24250080, 27500000, 1, 1, 2016667, 2016667, 60}, + {258, 24250080, 27500000, 24250080, 27500000, 2, 2, 2016667, 2016667, 120}, + {260, 37000020, 40000000, 37000020, 40000000, 1, 1, 2229166, 2229166, 60}, + {260, 37000080, 40000000, 37000080, 40000000, 2, 2, 2229167, 2229167, 120}, + {261, 27500040, 28350000, 27500040, 28350000, 1, 1, 2070833, 2070833, 60}, + {261, 27500040, 28350000, 27500040, 28350000, 2, 2, 2070833, 2070833, 120}, + {510, 27500000, 28350000, 17300000, 20200000, 1, 4, 2070833, 1553336, 60}, + {510, 27500000, 28350000, 17300000, 20200000, 2, 8, 2070833, 1553336, 120}, + {511, 28350000, 30000000, 17300000, 20200000, 1, 4, 2084999, 1553336, 60}, + {511, 28350000, 30000000, 17300000, 20200000, 2, 8, 2084999, 1553336, 120}, + {512, 27500000, 30000000, 17300000, 20200000, 1, 4, 2070833, 1553336, 60}, + {512, 27500000, 30000000, 17300000, 20200000, 2, 8, 2070833, 1553336, 120}}; // synchronization raster per band tables (Rel.17) // (38.101-1 Table 5.4.3.3-1 and 38.101-2 Table 5.4.3.3-1) @@ -341,6 +346,13 @@ const sync_raster_t sync_raster[] = { {260, 4, 22996, 2, 23164}, {261, 3, 22446, 1, 22492}, {261, 4, 22446, 2, 22490}, + {510, 3, 17448, 12, 19428}, + {510, 4, 17472, 24, 19416}, + {511, 3, 17448, 12, 19428}, + {511, 4, 17472, 24, 19416}, + {512, 3, 17448, 12, 19428}, + {512, 4, 17472, 24, 19416}, +/***************************/ }; // clang-format on @@ -542,14 +554,6 @@ int get_nb_periods_per_frame(uint8_t tdd_period) return nb_periods_per_frame; } -void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs) -{ - uint32_t delta_arfcn = nrarfcn - N_OFFs; - - if(delta_arfcn % (nr_bandtable[i].step_size) != 0) - LOG_E(NR_MAC, "nrarfcn %u is not on the channel raster for step size %lu\n", nrarfcn, nr_bandtable[i].step_size); -} - uint32_t to_nrarfcn(uint64_t CarrierFreq) { uint64_t CarrierFreq_by_1k = CarrierFreq / 1000; @@ -580,7 +584,6 @@ uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn) int deltaFglobal = 5; uint32_t N_REF_Offs = 0; uint64_t F_REF_Offs_khz = 0; - uint64_t N_OFFs, frequency, freq_min; int i = get_nr_table_idx(nr_bandP, scs_index); if (nrarfcn > 599999 && nrarfcn < 2016667) { @@ -594,42 +597,30 @@ uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn) F_REF_Offs_khz = 24250080; } - int32_t delta_duplex = get_delta_duplex(nr_bandP, scs_index); + // First check if the ARFCN is on the RASTER + uint32_t stepsize = nr_bandtable[i].dl_stepsize; + uint32_t N_OFFs = nr_bandtable[i].N_OFFs_DL; - if (delta_duplex <= 0){ // DL band >= UL band - if (nrarfcn >= nr_bandtable[i].N_OFFs_DL){ // is TDD of FDD DL - N_OFFs = nr_bandtable[i].N_OFFs_DL; - freq_min = nr_bandtable[i].dl_min; - } else {// is FDD UL - N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex/deltaFglobal; - freq_min = nr_bandtable[i].ul_min; - } - } else { // UL band > DL band - if (nrarfcn >= nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal){ // is FDD UL - N_OFFs = nr_bandtable[i].N_OFFs_DL + delta_duplex / deltaFglobal; - freq_min = nr_bandtable[i].ul_min; - } else { // is FDD DL - N_OFFs = nr_bandtable[i].N_OFFs_DL; - freq_min = nr_bandtable[i].dl_min; + if (nrarfcn >= nr_bandtable[i].N_OFFs_UL) { + if (nr_bandtable[i].N_OFFs_UL > N_OFFs || nrarfcn < N_OFFs) { + N_OFFs = nr_bandtable[i].N_OFFs_UL; + stepsize = nr_bandtable[i].ul_stepsize; } } - LOG_D(NR_MAC, "Frequency from NR-ARFCN for N_OFFs %lu, duplex spacing %d KHz, deltaFglobal %d KHz\n", - N_OFFs, - delta_duplex, - deltaFglobal); + LOG_D(NR_MAC, "N_OFFs %u, deltaFglobal %d KHz, stepsize:%d\n", N_OFFs, deltaFglobal, stepsize); - AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %llu\n", nrarfcn, nr_bandtable[i].band, (long long unsigned int)N_OFFs); - get_delta_arfcn(i, nrarfcn, N_OFFs); + AssertFatal(nrarfcn >= N_OFFs,"nrarfcn %u < N_OFFs[%d] %u\n", nrarfcn, nr_bandtable[i].band, N_OFFs); - frequency = 1000 * (F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal); + if ((nrarfcn - N_OFFs) % stepsize != 0) + LOG_E(NR_MAC, "nrarfcn %u is not on the channel raster for step size %u. N_OFFS:%d\n", + nrarfcn, stepsize, N_OFFs); - LOG_D(NR_MAC, "Computing frequency (nrarfcn %llu => %llu KHz (freq_min %llu KHz, NR band %d N_OFFs %llu))\n", + uint64_t frequency = 1000 * (F_REF_Offs_khz + (nrarfcn - N_REF_Offs) * deltaFglobal); + LOG_I(NR_MAC, "Computing frequency (nrarfcn %llu => %llu KHz, NR band %d\n", (unsigned long long)nrarfcn, (unsigned long long)frequency/1000, - (unsigned long long)freq_min, - nr_bandP, - (unsigned long long)N_OFFs); + nr_bandP); return frequency; } @@ -1049,7 +1040,7 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB, // only difference wrt NR-ARFCN is delta frequency 5kHz if f < 3 GHz for ARFCN uint32_t absolute_diff = (absoluteFrequencySSB - absoluteFrequencyPointA); const int scaling_5khz = absoluteFrequencyPointA < 600000 ? 3 : 1; - const int scaling = frequency_range == FR2 ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing; + const int scaling = (absoluteFrequencyPointA >= 2016667) ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing; const int scaled_abs_diff = absolute_diff / (scaling_5khz * scaling); // absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total const int ssb_offset_point_a = ((scaled_abs_diff / 12) - 10) * scaling; @@ -1358,11 +1349,14 @@ long rrc_get_max_nr_csrs(const int max_rbs, const long b_SRS) frequency_range_t get_freq_range_from_freq(uint64_t freq) { - // 3GPP TS 38.101-1 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // 3GPP TS 38.101-1,38.101-5 Version 19.0.0 Table 5.1-1: Definition of frequency ranges if (freq >= 410000000 && freq <= 7125000000) return FR1; - - if (freq >= 24250000000 && freq <= 71000000000) + // 3GPP TS 38.101-1 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // FR2 is from 24250 MHz –to 71000 MHz + // 3GPP TS 38.101-5 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // FR2 for NTN is from 17300 Mhz to 30000 MHz + if (freq >= 17300000000 && freq <= 71000000000) return FR2; AssertFatal(false, "Undefined Frequency Range for frequency %ld Hz\n", freq); @@ -1373,8 +1367,11 @@ frequency_range_t get_freq_range_from_arfcn(uint32_t arfcn) // 3GPP TS 38.101-1 Version 19.0.0 Table 5.1-1: Definition of frequency ranges if (arfcn >= 82000 && arfcn <= 875000) return FR1; - - if (arfcn >= 2016667 && arfcn <= 2795832) + // 3GPP TS 38.101-1 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // FR2 is from 24250 MHz –to 71000 MHz (from ARFCN 2016667) + // 3GPP TS 38.101-5 Version 19.0.0 Table 5.1-1: Definition of frequency ranges + // FR2 for NTN is from 17300 Mhz to 30000 MHz, from ARFCN 1553336 (Table 5.4.2.3-3) + if (arfcn >= 1553336 && arfcn <= 2795832) return FR2; AssertFatal(false, "Undefined Frequency Range for ARFCN %d\n", arfcn); diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 58dad544cc..685d4422b6 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -107,8 +107,10 @@ typedef struct nr_bandentry_s { uint64_t ul_max; uint64_t dl_min; uint64_t dl_max; - uint64_t step_size; - uint64_t N_OFFs_DL; + uint8_t ul_stepsize; + uint8_t dl_stepsize; + uint32_t N_OFFs_UL; + uint32_t N_OFFs_DL; uint8_t deltaf_raster; } nr_bandentry_t; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 11dac69484..b1765f7c38 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1184,6 +1184,7 @@ typedef struct { } nr_prach_info_3gpp_fr2_t; // Table 6.3.3.2-4: Random access configurations for FR2 and unpaired spectrum +// and NTN-FR2 and paired as defined in 38.211v18.06 static const nr_prach_info_3gpp_fr2_t table_6_3_3_2_4_prachConfig_Index[256] = { // format, format, x, y, y, SFN_nbr, star_symb, slots_sfn, occ_slot, // duration @@ -1458,7 +1459,8 @@ int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_ran if (frequency_range==FR1) format = table_6_3_3_2_2_prachConfig_Index[index].format; else - AssertFatal(0==1,"no paired spectrum for FR2\n"); + // Table defined for NTN-FR2 and paired in 3GPP Spec 38.211v18.06 + format = table_6_3_3_2_4_prachConfig_Index[index].format; } return format; } From 1f3faac18fa56c18a39a0b8ee690de3af5e9524f Mon Sep 17 00:00:00 2001 From: Raghavendra Dinavahi Date: Thu, 11 Dec 2025 18:21:46 +0100 Subject: [PATCH 10/30] Added Conf files for NTN-FR2 band512, SCS-BW: 120Khz-50, 100Mhz, 200Mhz --- .../gnb.sa.band512.ntn.mu3.132prb.rfsim.conf | 275 +++++++++++++++++ .../gnb.sa.band512.ntn.mu3.32prb.rfsim.conf | 276 ++++++++++++++++++ .../gnb.sa.band512.ntn.mu3.66prb.rfsim.conf | 276 ++++++++++++++++++ 3 files changed, 827 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.132prb.rfsim.conf create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.32prb.rfsim.conf create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.66prb.rfsim.conf diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.132prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.132prb.rfsim.conf new file mode 100644 index 0000000000..446223843e --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.132prb.rfsim.conf @@ -0,0 +1,275 @@ +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, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + CSI_report_type = "ssb_sinr"; + min_rxtxtime = 6; + disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # GSCN + absoluteFrequencySSB = 1556256; + dl_frequencyBand = 512; + # This is SSB ARFCN - ((offset RBs accg to controlResourceSetZero + 10 rbs for half of SSB) * 12(num REs) * 8 (raster 120khz/15Khz)) + dl_absoluteFrequencyPointA = 1553952; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 3; + dl_carrierBandwidth = 132; + #initialDownlinkBWP + #genericParameters + # This is RBstart = 0, L = 32: (275 * (L - 1)) + RBstart + initialDLBWPlocationAndBandwidth = 36025; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 3; + #pdcch-ConfigCommon + # Value 0 - 2symbols for coreset, 0 Rbs offset, does not work until code changed in nr_rrc_config_dl_tda + # as len_coreset is hard coded to 1 TBD to fix this + # Value 2 - 1 symbol for coreset, 14 rbs offset + initialDLBWPcontrolResourceSetZero = 2; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_absoluteFrequencyPointA = 2070987; + ul_frequencyBand = 512; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 3; + ul_carrierBandwidth = 132; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 36025; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 3; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 71; +#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; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 3; +# 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 = -70; + + 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 = 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 = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; # GEO satellite + ta-Common-r17 = 58629850; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +rlc = { + srb = { + t_poll_retransmit = "ms2000" + } + drb_am = { + t_poll_retransmit = "ms2000" + } +} + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + sl_ahead = 10; + bands = [512]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 60; + eNB_instances = [0]; + sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal" +} +); + + +rfsimulator = ( +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + prop_delay = 238.74; + IQfile = "/tmp/rfsimulator.iqs"; +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="info"; + f1ap_log_level ="info"; +}; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.32prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.32prb.rfsim.conf new file mode 100644 index 0000000000..7fb33a7a6e --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.32prb.rfsim.conf @@ -0,0 +1,276 @@ +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, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + + CSI_report_type = "ssb_sinr"; + min_rxtxtime = 6; + disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # GSCN + absoluteFrequencySSB = 1556256; + dl_frequencyBand = 512; + # This is SSB ARFCN - ((offset RBs accg to controlResourceSetZero + 10 rbs for half of SSB) * 12(num REs) * 8 (raster 120khz/15Khz)) + dl_absoluteFrequencyPointA = 1554496; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 3; + dl_carrierBandwidth = 32; + #initialDownlinkBWP + #genericParameters + # This is RBstart = 0, L = 32: (275 * (L - 1)) + RBstart + initialDLBWPlocationAndBandwidth = 8525; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 3; + #pdcch-ConfigCommon + # Value 0 - 2symbols for coreset, 0 Rbs offset, does not work until code changed in nr_rrc_config_dl_tda + # as len_coreset is hard coded to 1 TBD to fix this + # Value 2 - 1 symbol for coreset, 14 rbs offset + initialDLBWPcontrolResourceSetZero = 1; + initialDLBWPsearchSpaceZero = 2; // to push sib1 into slot other than 0, otherwise RBs are not enough + + #uplinkConfigCommon + #frequencyInfoUL + ul_absoluteFrequencyPointA = 2070833; + ul_frequencyBand = 512; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 3; + ul_carrierBandwidth = 32; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 8525; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 3; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 58; +#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; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 3; +# 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 = -70; + + 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 = 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 = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; # GEO satellite + ta-Common-r17 = 58629850; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + + +rlc = { + srb = { + t_poll_retransmit = "ms2000" + } + drb_am = { + t_poll_retransmit = "ms2000" + } +} + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + sl_ahead = 10; + bands = [512]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 60; + eNB_instances = [0]; + sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal" +} +); + +rfsimulator = ( +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + prop_delay = 238.74; + IQfile = "/tmp/rfsimulator.iqs"; +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="info"; + f1ap_log_level ="info"; +}; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.66prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.66prb.rfsim.conf new file mode 100644 index 0000000000..3fddfd0890 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band512.ntn.mu3.66prb.rfsim.conf @@ -0,0 +1,276 @@ +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, sd = 0xffffff }) }); + nr_cellid = 12345678L; + + ////////// Physical parameters: + CSI_report_type = "ssb_sinr"; + min_rxtxtime = 6; + disable_harq = 1; + cu_sibs = [2]; + du_sibs = [19]; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + #GSCN + absoluteFrequencySSB = 1558560; + dl_frequencyBand = 512; + # This is SSB ARFCN - ((offset RBs accg to controlResourceSetZero + 10 rbs for half of SSB) * 12(num REs) * 8 (raster 120khz/15Khz)) + dl_absoluteFrequencyPointA = 1556064; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 3; + dl_carrierBandwidth = 66; + #initialDownlinkBWP + #genericParameters + # This is RBstart = 0, L = 32: (275 * (L - 1)) + RBstart + initialDLBWPlocationAndBandwidth = 17875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 3; + #pdcch-ConfigCommon + # Value 0 - 2symbols for coreset, 0 Rbs offset, does not work until code changed in nr_rrc_config_dl_tda + # as len_coreset is hard coded to 1 TBD to fix this + # Value 2 - 1 symbol for coreset, 14 rbs offse + initialDLBWPcontrolResourceSetZero = 2; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_absoluteFrequencyPointA = 2070833; + ul_frequencyBand = 512; + #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 = 58; +#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; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 3; +# 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 = -70; + + 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 = 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 = -25; + + #ext2 + #ntn_Config_r17 + cellSpecificKoffset_r17 = 478; # GEO satellite + ta-Common-r17 = 58629850; + positionX-r17 = 0; + positionY-r17 = 0; + positionZ-r17 = 32433846; + velocityVX-r17 = 0; + velocityVY-r17 = 0; + velocityVZ-r17 = 0; + } + + ); + + TIMERS : + { + sr_ProhibitTimer = 0; + sr_TransMax = 64; + sr_ProhibitTimer_v1700 = 512; + t300 = 2000; + t301 = 2000; + t319 = 2000; + }; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.71.132"; }); + + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/26"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.140/26"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + + +rlc = { + srb = { + t_poll_retransmit = "ms2000" + } + drb_am = { + t_poll_retransmit = "ms2000" + } +} + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + sl_ahead = 10; + bands = [512]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 60; + eNB_instances = [0]; + sdr_addrs = "mgmt_addr=192.168.10.2,addr=192.168.10.2,clock_source=internal,time_source=internal" +} +); + + +rfsimulator = ( +{ + serveraddr = "server"; + serverport = 4043; + options = (); #("saviq"); or/and "chanmod" + prop_delay = 238.74; + IQfile = "/tmp/rfsimulator.iqs"; +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="info"; + f1ap_log_level ="info"; +}; From f6c04c26725574960ea93e5576ae8dbcf76bf689 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 3 Mar 2026 18:31:12 +0100 Subject: [PATCH 11/30] COMMON: fix ssb_offset_point_a calculation Even though the NR ARFCN uses a 15 kHz raster until 24250 MHz, the ssb_offset_point_a is still scaled by 60 kHz for FR2. So we need two different scaling factors. --- common/utils/nr/nr_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 4ed820c03f..a0273bcf56 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1043,9 +1043,10 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB, const int scaling = (absoluteFrequencyPointA >= 2016667) ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing; const int scaled_abs_diff = absolute_diff / (scaling_5khz * scaling); // absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total - const int ssb_offset_point_a = ((scaled_abs_diff / 12) - 10) * scaling; + const int ssb_offset_scaling = (frequency_range == FR2) ? 1 << (ssbSubcarrierSpacing - 2) : 1 << ssbSubcarrierSpacing; + const int ssb_offset_point_a = ((scaled_abs_diff / 12) - 10) * ssb_offset_scaling; // Offset to point A needs to be divisible by scaling - AssertFatal(ssb_offset_point_a % scaling == 0, "PRB offset %d not valid for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); + AssertFatal(ssb_offset_point_a % ssb_offset_scaling == 0, "PRB offset %d not valid for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); AssertFatal(ssb_offset_point_a >= 0, "ssb offset is negative %d for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); return ssb_offset_point_a; } From a240e21ddd61f4f88b0a4e5f777aad5d92afbb44 Mon Sep 17 00:00:00 2001 From: Mario Joa-Ng Date: Wed, 4 Mar 2026 14:45:51 -0500 Subject: [PATCH 12/30] remove xran_fh_tx_send_slot_BySymbol() and xran_fh_rx_read_slot_BySymbol() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Teodora Vladić --- radio/fhi_72/oaioran.c | 541 +++++------------------------------- radio/fhi_72/oran_isolate.c | 18 +- radio/fhi_72/oran_isolate.h | 6 - 3 files changed, 79 insertions(+), 486 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 047c216898..51d6e2b4cf 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -566,17 +566,31 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) #if defined F_RELEASE numRB = pRbElm->UP_nRBSize; startRB = pRbElm->UP_nRBStart; + struct xran_section_desc *p_sec_desc = &pRbElm->sec_desc[sym_idx][0]; #endif LOG_D(HW, "pPrbMap[%d] : PRBstart %d nPRBs %d\n", idxElm, startRB, numRB); - 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; + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. + if (fh_cfg->RunSlotPrbMapBySymbolEnable) { + if (sym_idx >= pRbElm->nStartSymb && sym_idx < pRbElm->nStartSymb + pRbElm->numSymb) { + if (!p_sec_desc->pCtrl) + continue; + // 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 { + 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; + } } } } @@ -592,6 +606,34 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) if (!is_tdd_dl_guard_slot(frame_conf, slot)) { continue; } + + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable. Set nPrbElm if beam_id = -1 for all downlink symbols + if (fh_cfg->RunSlotPrbMapBySymbolEnable) { + bool beam_used = false; + uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; + struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; + struct xran_prb_map *pRbMap = pPrbMap; + int32_t dl_sym_end = 0; + for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { + if (is_tdd_dl_symbol(frame_conf, slot, sym_idx)) { + if (ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT+ sym_idx] != -1) + beam_used |= true; + } + else { + dl_sym_end = sym_idx; + break; + } + } + if (is_tdd_guard_slot(frame_conf, slot)) + pRbMap->nPrbElm = dl_sym_end; + else + pRbMap->nPrbElm = XRAN_NUM_OF_SYMBOL_PER_SLOT; + if (!beam_used) { + pRbMap->nPrbElm = 0; + continue; + } + } + // This loop would better be more inner to avoid confusion and maybe also errors. for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { /* skip UL and guard symbols. */ @@ -654,12 +696,36 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) int16_t numRB = p_prbMapElm->UP_nRBSize; #endif - dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); - if (p_sec_desc == NULL) { printf("p_sec_desc == NULL\n"); exit(-1); } + + // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. + if (fh_cfg->RunSlotPrbMapBySymbolEnable) { + /* skip, if not scheduled */ + if(sym_idx < p_prbMapElm->nStartSymb || sym_idx >= p_prbMapElm->nStartSymb + p_prbMapElm->numSymb){ + p_sec_desc->iq_buffer_offset = 0; + p_sec_desc->iq_buffer_len = 0; + continue; + } + // 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+ 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 (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; + } + } + + dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); + uint16_t *dst16 = (uint16_t *)dst; if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) { @@ -721,456 +787,3 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) } return (0); } - -#if defined F_RELEASE -/** @details Read PRACH and PUSCH data from xran buffers. If - * I/Q compression (bitwidth < 16 bits) is configured, deccompresses the data - * before writing. Prints ON TIME counters every 128 frames. - * - * Function is blocking and waits for next frame/slot combination. It is unblocked - * by oai_xran_fh_rx_callback(). It writes the current slot into parameters - * frame/slot. */ -int xran_fh_rx_read_slot_BySymbol(ru_info_t *ru, int *frame, int *slot) -{ - void *ptr = NULL; - int32_t *pos = NULL; - int idx = 0; - - static int64_t old_rx_counter[XRAN_PORTS_NUM] = {0}; - static int64_t old_tx_counter[XRAN_PORTS_NUM] = {0}; - struct xran_common_counters x_counters[XRAN_PORTS_NUM]; - static int outcnt = 0; - #ifndef USE_POLLING - // pull next even from oran_sync_fifo - notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo); - - notifiedFIFO_elt_t *f; - while ((f = pollNotifiedFIFO(&oran_sync_fifo)) != NULL) { - oran_sync_info_t *old_info = NotifiedFifoData(res); - oran_sync_info_t *new_info = NotifiedFifoData(f); - LOG_E(HW, "Detected double sync message %d.%d => %d.%d\n", old_info->f, old_info->sl, new_info->f, new_info->sl); - delNotifiedFIFO_elt(res); - res = f; - } - - oran_sync_info_t *info = NotifiedFifoData(res); - - *slot = info->sl; - *frame = info->f; - delNotifiedFIFO_elt(res); -#else - *slot = oran_sync_info.sl; - *frame = oran_sync_info.f; - uint32_t tti_in = oran_sync_info.tti; - - static int last_slot = -1; - LOG_D(HW, "oran slot %d, last_slot %d\n", *slot, last_slot); - int cnt = 0; - // while (*slot == last_slot) { - while (tti_in == oran_sync_info.tti) { - //*slot = oran_sync_info.sl; - cnt++; - } - LOG_D(HW, "cnt %d, Reading %d.%d\n", cnt, *frame, *slot); - last_slot = *slot; -#endif - // return(0); - - struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int slots_per_frame = 10 << fh_cfg->frame_conf.nNumerology; - - int tti = slots_per_frame * (*frame) + (*slot); - - read_prach_data(ru, *frame, *slot); - - const struct xran_fh_init *fh_init = get_xran_fh_init(); - int nPRBs = fh_cfg->nULRBs; - int fftsize = 1 << fh_cfg->nULFftSize; - - int slot_offset_rxdata = 3 & (*slot); - uint32_t slot_size = 4 * 14 * fftsize; - uint8_t *rx_data = (uint8_t *)ru->rxdataF[0]; - uint8_t *start_ptr = NULL; - int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; - 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++) { - rx_data = (uint8_t *)ru->rxdataF[ant_id]; - start_ptr = rx_data + (slot_size * slot_offset_rxdata); - 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)) - continue; - bool sym_start_found = false; - int32_t sym_start = 0; - // This loop would better be more inner to avoid confusion and maybe also errors. - for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - /* the callback is for mixed and UL slots. In mixed, we have to - * skip DL and guard symbols. */ - if (!is_tdd_ul_symbol(frame_conf, *slot, sym_idx)) - continue; - if (!sym_start_found) { - sym_start = sym_idx; - sym_start_found = true; - } - - uint8_t *pData; - oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru); - uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; - struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; - - struct xran_prb_map *pRbMap = pPrbMap; - for (int idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { - struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm]; - struct xran_section_desc *p_sec_desc = &pRbElm->sec_desc[sym_idx][0]; - pData = p_sec_desc->pData; - ptr = pData; - pos = (int32_t *)(start_ptr + (4 * sym_idx * fftsize)); - if (ptr == NULL || pos == NULL) - continue; - - uint8_t *src = (uint8_t *)ptr; - - LOG_D(HW, "rx pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); - // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. - u_int8_t section_id_tmp = pPrbMap->nPrbElm < XRAN_NUM_OF_SYMBOL_PER_SLOT ? sym_idx - sym_start: sym_idx; - if (section_id_tmp != pRbElm->nSectId) { - LOG_D(HW, - "rx prbMap[%d] : PRBstart %d nPRBs %d nSectId %d != sym_idx %d:%d\n", - idxElm, - pRbMap->prbMap[idxElm].nRBStart, - pRbMap->prbMap[idxElm].nRBSize, - pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp - ); - continue; - } - LOG_D(HW, - "rx prbMap[%d] : PRBstart %d:%d nPRBs %d:%d nSectId %d sym_idx %d:%d\n", - idxElm, - pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].UP_nRBStart, - pRbMap->prbMap[idxElm].nRBSize, pRbMap->prbMap[idxElm].UP_nRBSize, - pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp - ); - - int pos_len = 0; - int neg_len = 0; - int num_prbu = p_sec_desc->num_prbu; - int start_prbu = p_sec_desc->start_prbu; - if (start_prbu < (nPRBs >> 1)) // there are PRBs left of DC - neg_len = min((nPRBs * 6) - (start_prbu * 12), num_prbu * N_SC_PER_PRB); - pos_len = (num_prbu * N_SC_PER_PRB) - neg_len; - - src = pData; - // Calculation of the pointer for the section in the buffer. - // positive half - uint8_t *dst1 = (uint8_t *)(pos + (neg_len == 0 ? ((start_prbu * N_SC_PER_PRB) - (nPRBs * 6)) : 0)); - // negative half - uint8_t *dst2 = (uint8_t *)(pos + (start_prbu * N_SC_PER_PRB) + fftsize - (nPRBs * 6)); - int32_t local_dst[num_prbu * N_SC_PER_PRB] __attribute__((aligned(64))); - if (pRbElm->compMethod == XRAN_COMPMETHOD_NONE) { - // NOTE: gcc 11 knows how to generate AVX2 for this! - for (idx = 0; idx < num_prbu * N_SC_PER_PRB * 2; idx++) - ((int16_t *)local_dst)[idx] = ((int16_t)ntohs(((uint16_t *)src)[idx])) >> 2; - memcpy((void *)dst2, (void *)local_dst, neg_len * 4); - memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4); - } else if (pRbElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { -#if defined(__i386__) || defined(__x86_64__) - struct xranlib_decompress_request bfp_decom_req = {}; - struct xranlib_decompress_response bfp_decom_rsp = {}; - - int16_t payload_len = (3 * pRbElm->iqWidth + 1) * num_prbu; - - bfp_decom_req.data_in = (int8_t *)src; - bfp_decom_req.numRBs = num_prbu; - bfp_decom_req.len = payload_len; - bfp_decom_req.compMethod = pRbElm->compMethod; - bfp_decom_req.iqWidth = pRbElm->iqWidth; - - bfp_decom_rsp.data_out = (int16_t *)local_dst; - bfp_decom_rsp.len = 0; - - xranlib_decompress_avx512(&bfp_decom_req, &bfp_decom_rsp); -#elif defined(__arm__) || defined(__aarch64__) - armral_bfp_decompression(pRbElm->iqWidth, num_prbu, (int8_t *)src, (int16_t *)local_dst); -#else - AssertFatal(1 == 0, "BFP compression not supported on this architecture"); -#endif - memcpy((void *)dst2, (void *)local_dst, neg_len * 4); - memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4); - outcnt++; - } else { - printf("pRbElm->compMethod == %d is not supported\n", pRbElm->compMethod); - exit(-1); - } - } - } // sym_ind - } // ant_ind - } // vv_inf - if ((*frame & 0x7f) == 0 && *slot == 0 && xran_get_common_counters(gxran_handle, &x_counters[0]) == XRAN_STATUS_SUCCESS) { - for (int o_xu_id = 0; o_xu_id < fh_init->xran_ports; o_xu_id++) { - LOG_I(HW, - "[%s%d][rx %7ld pps %7ld kbps %7ld][tx %7ld pps %7ld kbps %7ld][Total Msgs_Rcvd %ld]\n", - "o-du ", - o_xu_id, - x_counters[o_xu_id].rx_counter, - x_counters[o_xu_id].rx_counter - old_rx_counter[o_xu_id], - x_counters[o_xu_id].rx_bytes_per_sec * 8 / 1000L, - x_counters[o_xu_id].tx_counter, - x_counters[o_xu_id].tx_counter - old_tx_counter[o_xu_id], - x_counters[o_xu_id].tx_bytes_per_sec * 8 / 1000L, - x_counters[o_xu_id].Total_msgs_rcvd); - for (int rxant = 0; rxant < ru->nb_rx / fh_init->xran_ports; rxant++) - LOG_I(HW, - "[%s%d][pusch%d %7ld prach%d %7ld]\n", - "o_du", - o_xu_id, - rxant, - x_counters[o_xu_id].rx_pusch_packets[rxant], - rxant, - x_counters[o_xu_id].rx_prach_packets[rxant]); - if (x_counters[o_xu_id].rx_counter > old_rx_counter[o_xu_id]) - old_rx_counter[o_xu_id] = x_counters[o_xu_id].rx_counter; - if (x_counters[o_xu_id].tx_counter > old_tx_counter[o_xu_id]) - old_tx_counter[o_xu_id] = x_counters[o_xu_id].tx_counter; - } - } - return (0); -} - -/** @details Write PDSCH IQ-data from OAI txdataF_BF buffer to xran buffers. If - * I/Q compression (bitwidth < 16 bits) is configured, compresses the data - * before writing. */ -int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t timestamp) -{ - int tti = /*frame*SUBFRAMES_PER_SYSTEMFRAME*SLOTNUM_PER_SUBFRAME+*/ 20 * frame - + slot; // commented out temporarily to check that compilation of oran 5g is working. - - void *ptr = NULL; - int32_t *pos = NULL; - int idx = 0; - - const struct xran_fh_init *fh_init = get_xran_fh_init(); - const struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int nPRBs = fh_cfg->nDLRBs; - int fftsize = 1 << fh_cfg->nDLFftSize; - int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports; - int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; - - // Handle CP UL packet here instead of at xran_fh_rx_read_slot() as oran_fh_if4p5_south_in() lags behind - // oran_fh_if4p5_south_out() (which is invoked at the right time slot) by 4 slots. - // 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++) { - 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)) { - continue; - } - bool sym_start_found = false; - int32_t sym_start = 0; - // This loop would better be more inner to avoid confusion and maybe also errors. - for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - /* the callback is for mixed and UL slots. In mixed, we have to - * skip DL and guard symbols. */ - if (!is_tdd_ul_symbol(frame_conf, slot, sym_idx)) { - continue; - } - if (!sym_start_found) { - sym_start = sym_idx; - sym_start_found = true; - } - - oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru); - uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; - struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; - - struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[0]; - - struct xran_prb_map *pRbMap = pPrbMap; - uint32_t idxElm = 0; - - LOG_D(HW, "tx0 pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); - for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { - LOG_D(HW, "prbMap[%d] : PRBstart %d nPRBs %d\n", idxElm, pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].nRBSize); - pRbElm = &pRbMap->prbMap[idxElm]; - // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. - u_int8_t section_id_tmp = pPrbMap->nPrbElm < XRAN_NUM_OF_SYMBOL_PER_SLOT ? sym_idx - sym_start: sym_idx; - if (section_id_tmp != pRbElm->nSectId) { - LOG_D(HW, - "tx0 prbMap[%d] : PRBstart %d:%d nPRBs %d:%d nSectId %d != sym_idx %d:%d\n", - idxElm, - pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].UP_nRBStart, - pRbMap->prbMap[idxElm].nRBSize, pRbMap->prbMap[idxElm].UP_nRBSize, - pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp - ); - continue; - } - LOG_D(HW, - "tx0 prbMap[%d] : PRBstart %d:%d nPRBs %d:%d nSectId %d sym_idx %d:%d\n", - idxElm, - pRbMap->prbMap[idxElm].nRBStart, pRbMap->prbMap[idxElm].UP_nRBStart, - pRbMap->prbMap[idxElm].nRBSize, pRbMap->prbMap[idxElm].UP_nRBSize, - pRbMap->prbMap[idxElm].nSectId, sym_idx, section_id_tmp - ); - - // 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; - } - } - } - } - - 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_tx; ant_id++) { - oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_tx_per_ru); - const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_tx_per_ru)->frame_conf; - // skip processing this slot is TX (no TX in this slot) - if (!is_tdd_dl_guard_slot(frame_conf, slot)) { - continue; - } - - // Set nPrbElm if beam_id = -1 for all downlink symbols - bool beam_used = false; - uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; - struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; - struct xran_prb_map *pRbMap = pPrbMap; - int32_t dl_sym_end = 0; - for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - if (is_tdd_dl_symbol(frame_conf, slot, sym_idx)) { - if (ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT+ sym_idx] != -1) - beam_used |= true; - } - else { - dl_sym_end = sym_idx; - break; - } - } - if (is_tdd_guard_slot(frame_conf, slot)) - pRbMap->nPrbElm = dl_sym_end; - else - pRbMap->nPrbElm = XRAN_NUM_OF_SYMBOL_PER_SLOT; - if (!beam_used) { - pRbMap->nPrbElm = 0; - continue; - } - - // This loop would better be more inner to avoid confusion and maybe also errors. - for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) { - /* the callback is for mixed and UL slots. In mixed, we have to - * skip UL and guard symbols. */ - if (is_tdd_ul_symbol(frame_conf, slot, sym_idx)) { - continue; - } - uint8_t *pData = - bufs->src[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT].pData; - uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData; - struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData; - ptr = pData; - pos = &ru->txdataF_BF[ant_id][sym_idx * fftsize]; - - uint8_t *u8dptr; - struct xran_prb_map *pRbMap = pPrbMap; - int32_t sym_id = sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT; - if (ptr && pos) { - uint32_t idxElm = 0; - u8dptr = (uint8_t *)ptr; - int16_t payload_len = 0; - - uint8_t *dst = (uint8_t *)u8dptr; - - struct xran_prb_elm *p_prbMapElm = &pRbMap->prbMap[idxElm]; - LOG_D(HW, "tx1 pRbMap->nPrbElm %d\n", pRbMap->nPrbElm); - for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) { - // For Liteon FR2 with RunSlotPrbMapBySymbolEnable xran_prb_map will have xran_prb_elm prbMap[14], each idxElm matches to sym_idx. - struct xran_section_desc *p_sec_desc = NULL; - p_prbMapElm = &pRbMap->prbMap[idxElm]; - if (sym_idx != p_prbMapElm->nSectId) - continue; - // 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+ 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 (p_prbMapElm->nBeamIndex == -1) - p_prbMapElm->nBeamIndex = 0; - - // assumes one fragment per symbol - p_sec_desc = &p_prbMapElm->sec_desc[sym_id][0]; - - dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); - - if (p_sec_desc == NULL) { - printf("p_sec_desc == NULL\n"); - exit(-1); - } - uint16_t *dst16 = (uint16_t *)dst; - - int pos_len = 0; - int neg_len = 0; - - if (p_prbMapElm->UP_nRBStart < (nPRBs >> 1)) // there are PRBs left of DC - neg_len = min((nPRBs * 6) - (p_prbMapElm->UP_nRBStart * 12), p_prbMapElm->UP_nRBSize * N_SC_PER_PRB); - pos_len = (p_prbMapElm->UP_nRBSize * N_SC_PER_PRB) - neg_len; - // Calculation of the pointer for the section in the buffer. - // start of positive frequency component - uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) - (nPRBs * 6)) : 0]; - // start of negative frequency component - uint16_t *src2 = (uint16_t *)&pos[(p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) + fftsize - (nPRBs * 6)]; - - uint32_t local_src[p_prbMapElm->UP_nRBSize * N_SC_PER_PRB] __attribute__((aligned(64))); - memcpy((void *)local_src, (void *)src2, neg_len * 4); - memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4); - if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) { - payload_len = p_prbMapElm->UP_nRBSize * N_SC_PER_PRB * 4L; - /* convert to Network order */ - // NOTE: ggc 11 knows how to generate AVX2 for this! - for (idx = 0; idx < (pos_len + neg_len) * 2; idx++) - ((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx]); - } else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { - payload_len = (3 * p_prbMapElm->iqWidth + 1) * p_prbMapElm->UP_nRBSize; - -#if defined(__i386__) || defined(__x86_64__) - struct xranlib_compress_request bfp_com_req = {}; - struct xranlib_compress_response bfp_com_rsp = {}; - - bfp_com_req.data_in = (int16_t *)local_src; - bfp_com_req.numRBs = p_prbMapElm->UP_nRBSize; - bfp_com_req.len = payload_len; - bfp_com_req.compMethod = p_prbMapElm->compMethod; - bfp_com_req.iqWidth = p_prbMapElm->iqWidth; - - bfp_com_rsp.data_out = (int8_t *)dst; - bfp_com_rsp.len = 0; - - xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp); -#elif defined(__arm__) || defined(__aarch64__) - armral_bfp_compression(p_prbMapElm->iqWidth, p_prbMapElm->UP_nRBSize, (int16_t *)local_src, (int8_t *)dst); -#else - AssertFatal(1 == 0, "BFP compression not supported on this architecture"); -#endif - - } else { - printf("p_prbMapElm->compMethod == %d is not supported\n", p_prbMapElm->compMethod); - exit(-1); - } - - p_sec_desc->iq_buffer_offset = RTE_PTR_DIFF(dst, u8dptr); - p_sec_desc->iq_buffer_len = payload_len; - - dst += payload_len; - dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod); - } - - // The tti should be updated as it increased. - pRbMap->tti_id = tti; - - } else { - printf("ptr ==NULL\n"); - exit(-1); // fails here?? - } - } - } - } - return (0); -} -#endif \ No newline at end of file diff --git a/radio/fhi_72/oran_isolate.c b/radio/fhi_72/oran_isolate.c index 0ec4867299..d19d2c1f00 100644 --- a/radio/fhi_72/oran_isolate.c +++ b/radio/fhi_72/oran_isolate.c @@ -227,14 +227,7 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot) int f, sl; LOG_D(HW, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]); start_meas(&ru->rx_fhaul); - struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int ret = 0; -#if defined F_RELEASE - if (fh_cfg->RunSlotPrbMapBySymbolEnable) - ret = xran_fh_rx_read_slot_BySymbol(&ru_info, &f, &sl); - else -#endif - ret = xran_fh_rx_read_slot(&ru_info, &f, &sl); + int ret = xran_fh_rx_read_slot(&ru_info, &f, &sl); stop_meas(&ru->rx_fhaul); LOG_D(HW, "Read %d.%d rxdataF %p,%p\n", f, sl, ru_info.rxdataF[0], ru_info.rxdataF[1]); if (ret != 0) { @@ -289,14 +282,7 @@ void oran_fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) // printf("south_out:\tframe=%d\tslot=%d\ttimestamp=%ld\n",frame,slot,timestamp); - struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int ret = 0; -#if defined F_RELEASE - if (fh_cfg->RunSlotPrbMapBySymbolEnable) - ret = xran_fh_tx_send_slot_BySymbol(&ru_info, frame, slot, timestamp); - else -#endif - ret = xran_fh_tx_send_slot(&ru_info, frame, slot, timestamp); + int ret = xran_fh_tx_send_slot(&ru_info, frame, slot, timestamp); if (ret != 0) { printf("ORAN: ORAN_fh_if4p5_south_out ERROR in TX function \n"); } diff --git a/radio/fhi_72/oran_isolate.h b/radio/fhi_72/oran_isolate.h index 44c9bee51d..6d7a47811b 100644 --- a/radio/fhi_72/oran_isolate.h +++ b/radio/fhi_72/oran_isolate.h @@ -61,13 +61,7 @@ typedef struct ru_info_s { * @param frame output of the frame which has been read. * @param slot output of the slot which has been read. */ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot); -#if defined F_RELEASE -int xran_fh_rx_read_slot_BySymbol(ru_info_t *ru, int *frame, int *slot); -#endif /** @brief Writes TX data (PDSCH) of given slot. */ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp); -#if defined F_RELEASE -int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t timestamp); -#endif #endif /* _ORAN_ISOLATE_H_ */ From d7512bdc8b62c033b9ef8ebeb46772a64b50dfd1 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 27 Feb 2026 18:01:25 +0000 Subject: [PATCH 13/30] oaioran: fix compression for arm read data from start PRB of each section. --- radio/fhi_72/oaioran.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 047c216898..7f858219ac 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -693,7 +693,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp); #elif defined(__arm__) || defined(__aarch64__) - armral_bfp_compression(p_prbMapElm->iqWidth, numRB, (int16_t *)local_src, (int8_t *)dst); + armral_bfp_compression(p_prbMapElm->iqWidth, numRB, (int16_t *)(local_src + startRB * N_SC_PER_PRB), (int8_t *)dst); #else AssertFatal(1 == 0, "BFP compression not supported on this architecture"); #endif From 044ca835d621ae24c1bef084629bc1af440bcd03 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 23 Sep 2025 04:21:38 +0000 Subject: [PATCH 14/30] phy: use fftshift'ed buffer for txdataF So far txdataF buffer has DC RE as the first element. This was prefered most likely to avoid memcpy before iFFT but comes with a small complexity in RE mapping functions. Instead, we use a flat buffer that holds freq domain data starting from first negative SC. After resource mapping is done on all channels, each OFDM symbol is shifted before iFFT so that the buffer start with DC RE. This reduces complexity in mapping functions and later on when passing beam IDs to 7.2 split RU especially when a beam is associated to interleaved RB and/or REs. There is already a memcpy in place to copy txdataF from gNB stuct to RU struct. So this change does not introduce new memcpy. --- openair1/PHY/INIT/nr_init_ru.c | 3 +- openair1/PHY/MODULATION/nr_modulation.h | 9 ++ openair1/PHY/MODULATION/ofdm_mod.c | 48 +++++--- openair1/PHY/NR_TRANSPORT/nr_dci.c | 9 +- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 108 +++++------------- openair1/PHY/NR_TRANSPORT/nr_pbch.c | 37 +----- openair1/PHY/NR_TRANSPORT/nr_prs.c | 11 +- openair1/PHY/NR_TRANSPORT/nr_pss.c | 6 +- openair1/PHY/NR_TRANSPORT/nr_sss.c | 5 +- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 9 +- .../nr_phy_common/src/nr_phy_common_csirs.c | 4 +- openair1/SCHED_NR/nr_ru_procedures.c | 18 +-- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 1 + openair1/SIMULATION/NR_PHY/dlsim.c | 21 +++- openair1/SIMULATION/NR_PHY/pbchsim.c | 32 +++++- radio/fhi_72/oaioran.c | 81 ++++++------- 16 files changed, 185 insertions(+), 217 deletions(-) diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 21b564d3c2..1092545705 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -103,7 +103,8 @@ void nr_phy_init_RU(RU_t *ru) ru->common.txdataF_BF = (int32_t **)malloc16(nb_tx_streams * sizeof(int32_t*)); LOG_D(PHY, "[INIT] common.txdata_BF= %p (%lu bytes)\n", ru->common.txdataF_BF, nb_tx_streams * sizeof(int32_t *)); for (int i = 0; i < nb_tx_streams; i++) { - ru->common.txdataF_BF[i] = (int32_t*)malloc16_clear(fp->samples_per_subframe_wCP * sizeof(int32_t)); + ru->common.txdataF_BF[i] = + (int32_t *)malloc16_clear(fp->samples_per_slot_wCP * sizeof(int32_t)); LOG_D(PHY, "txdataF_BF[%d] %p for RU %d\n", i, ru->common.txdataF_BF[i], ru->idx); } // allocate FFT output buffers (RX) diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index 9e8ac3ba3c..fda32fa86f 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -105,6 +105,7 @@ void nr_beam_precoding(c16_t **txdataF, void apply_nr_rotation_TX(const NR_DL_FRAME_PARMS *fp, c16_t *txdataF, + bool is_flat_buff, const c16_t *symbol_rotation, int slot, int nb_rb, @@ -161,4 +162,12 @@ void nr_layer_precoder_simd(const int n_layers, const int sc_offset, const int re_cnt, c16_t *txdataF_precoded); + +void fft_shift(const c16_t *in, + uint32_t in_symb_sz, + uint16_t num_prb, + c16_t *out, + uint16_t fft_size_out, + uint16_t start_symb, + uint16_t num_symb); #endif diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index c3311fb78a..8a31648605 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -288,6 +288,7 @@ void do_OFDM_mod(c16_t **txdataF, c16_t **txdata, uint32_t frame,uint16_t next_s void apply_nr_rotation_TX(const NR_DL_FRAME_PARMS *fp, c16_t *txdataF, + bool is_flat_buff, const c16_t *symbol_rotation, int slot, int nb_rb, @@ -309,20 +310,39 @@ void apply_nr_rotation_TX(const NR_DL_FRAME_PARMS *fp, this_rotation->r, this_rotation->i); - if (nb_rb & 1) { - rotate_cpx_vector(this_symbol, this_rotation, this_symbol, - (nb_rb + 1) * 6, 15); - rotate_cpx_vector(this_symbol + fp->first_carrier_offset - 6, - this_rotation, - this_symbol + fp->first_carrier_offset - 6, - (nb_rb + 1) * 6, 15); - } else { - rotate_cpx_vector(this_symbol, this_rotation, this_symbol, - nb_rb * 6, 15); - rotate_cpx_vector(this_symbol + fp->first_carrier_offset, - this_rotation, - this_symbol + fp->first_carrier_offset, - nb_rb * 6, 15); + if (is_flat_buff) + rotate_cpx_vector(this_symbol, this_rotation, this_symbol, nb_rb * NR_NB_SC_PER_RB, 15); + else { + c16_t *this_symbol_neg = this_symbol + fp->first_carrier_offset; + if (nb_rb & 1) { + this_symbol_neg -= 6; + nb_rb += 1; + } + rotate_cpx_vector(this_symbol, this_rotation, this_symbol, nb_rb * 6, 15); + rotate_cpx_vector(this_symbol_neg, this_rotation, this_symbol_neg, nb_rb * 6, 15); } } } + +/* Do FFT-shift for symbols in the provided in buffer and writes to out buffer. */ +void fft_shift(const c16_t *in, + uint32_t in_symb_sz, + uint16_t num_prb, + c16_t *out, + uint16_t fft_size_out, + uint16_t start_symb, + uint16_t num_symb) +{ + const int num_samp_half = num_prb * NR_NB_SC_PER_RB / 2; + const int first_carrier_offset = fft_size_out - num_samp_half; + for (int s = start_symb; s < start_symb + num_symb; s++) { + // Copy negative freq component + uint16_t out_offset = s * fft_size_out + first_carrier_offset; + uint16_t in_offset = s * in_symb_sz; + memcpy(out + out_offset, in + in_offset, num_samp_half * sizeof(int32_t)); + // Copy positive freq component + out_offset = s * fft_size_out; + in_offset = s * in_symb_sz + num_samp_half; + memcpy(out + out_offset, in + in_offset, num_samp_half * sizeof(int32_t)); + } +} diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index edb296e8a4..a4f5c80989 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -67,7 +67,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, if (pdcch_pdu_rel15->CoreSetType == 1) additional_offset = (pdcch_pdu_rel15->BWPStart + 5) / 6 * 6 - pdcch_pdu_rel15->BWPStart; int rb_offset = cset_start + additional_offset; - uint16_t cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB; + uint16_t cset_start_sc = (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB; int idx1 = pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols; int idx2 = (((n_rb + rb_offset + pdcch_pdu_rel15->BWPStart) * 3) + 15) & ~15; c16_t mod_dmrs[idx1][idx2] __attribute__((aligned(16))); @@ -179,8 +179,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, /// Resource mapping uint16_t amp = gNB->TX_AMP; c16_t *txdataF = gNB->common_vars.txdataF[beam_nb][0]; - if (cset_start_sc >= frame_parms->ofdm_symbol_size) - cset_start_sc -= frame_parms->ofdm_symbol_size; int num_regs = dci_pdu->AggregationLevel * NR_NB_REG_PER_CCE / pdcch_pdu_rel15->DurationSymbols; /*Mapping the encoded DCI along with the DMRS */ @@ -189,8 +187,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, for (int reg_count = 0; reg_count < num_regs; reg_count++) { int k = cset_start_sc + reg_list[d][reg_count] * NR_NB_SC_PER_RB; LOG_D(NR_PHY_DCI, "REG %d k %d\n", reg_list[d][reg_count], k); - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; int l = cset_start_symb + symbol_idx; @@ -226,9 +222,6 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, } k++; - - if (k >= frame_parms->ofdm_symbol_size) - k -= frame_parms->ofdm_symbol_size; } // m } // reg_count } // symbol_idx diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index b09f816c7d..1edb590a58 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -86,8 +86,7 @@ static int do_ptrs_symbol(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, printf("k %d \t txdataF: %d %d\n", k, txF[k].r, txF[k].i); #endif } - if (++k >= symbol_sz) - k -= symbol_sz; + k++; } return in - tx_layer; } @@ -294,7 +293,7 @@ static inline int dmrs_case00(c16_t *output, else { output[k] = (c16_t){0}; } - k = (k + 1) % symbol_sz; + k++; } // RE loop return in - txl; } @@ -355,12 +354,6 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, { c16_t *txl = txl_start; const uint sz = rel15->rbSize * NR_NB_SC_PER_RB; - int upper_limit = sz; - int remaining_re = 0; - if (start_sc + upper_limit > symbol_sz) { - upper_limit = symbol_sz - start_sc; - remaining_re = sz - upper_limit; - } /* calculate if current symbol is PTRS symbols */ int ptrs_symbol = 0; @@ -385,47 +378,39 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, if (rel15->numDmrsCdmGrpsNoData == 2) { switch (dmrs_port & 3) { case 0: - txl += interleave_with_0_signal_first(output + start_sc, dmrs_start, amp_dmrs, upper_limit); - txl += interleave_with_0_signal_first(output, dmrs_start + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_signal_first(output + start_sc, dmrs_start, amp_dmrs, sz); break; case 1: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_with_0_signal_first(output + start_sc, dmrs, amp_dmrs, upper_limit); - txl += interleave_with_0_signal_first(output, dmrs + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_signal_first(output + start_sc, dmrs, amp_dmrs, sz); } break; case 2: - txl += interleave_with_0_start_with_0(output + start_sc, dmrs_start, amp_dmrs, upper_limit); - txl += interleave_with_0_start_with_0(output, dmrs_start + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_start_with_0(output + start_sc, dmrs_start, amp_dmrs, sz); break; case 3: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_with_0_start_with_0(output + start_sc, dmrs, amp_dmrs, upper_limit); - txl += interleave_with_0_start_with_0(output, dmrs + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_with_0_start_with_0(output + start_sc, dmrs, amp_dmrs, sz); } break; } } else if (rel15->numDmrsCdmGrpsNoData == 1) { switch (dmrs_port & 3) { case 0: - txl += interleave_signals(output + start_sc, txl, amp, dmrs_start, amp_dmrs, upper_limit); - txl += interleave_signals(output, txl, amp, dmrs_start + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_signals(output + start_sc, txl, amp, dmrs_start, amp_dmrs, sz); break; case 1: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_signals(output + start_sc, txl, amp, dmrs, amp_dmrs, upper_limit); - txl += interleave_signals(output, txl, amp, dmrs + upper_limit / 2, amp_dmrs, remaining_re); + txl += interleave_signals(output + start_sc, txl, amp, dmrs, amp_dmrs, sz); } break; case 2: - txl += interleave_signals(output + start_sc, dmrs_start, amp_dmrs, txl, amp, upper_limit); - txl += interleave_signals(output, dmrs_start + upper_limit / 2, amp_dmrs, txl, amp, remaining_re); + txl += interleave_signals(output + start_sc, dmrs_start, amp_dmrs, txl, amp, sz); break; case 3: { c16_t dmrs[sz / 2]; neg_dmrs(dmrs_start, dmrs, sz / 2); - txl += interleave_signals(output + start_sc, dmrs, amp_dmrs, txl, amp, upper_limit); - txl += interleave_signals(output, dmrs + upper_limit / 2, amp_dmrs, txl, amp, remaining_re); + txl += interleave_signals(output + start_sc, dmrs, amp_dmrs, txl, amp, sz); } break; } } else @@ -445,8 +430,7 @@ static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, rel15->numDmrsCdmGrpsNoData); } // generic DMRS case } else { // no PTRS or DMRS in this symbol - txl += no_ptrs_dmrs_case(output + start_sc, txl, amp, upper_limit); - txl += no_ptrs_dmrs_case(output, txl, amp, remaining_re); + txl += no_ptrs_dmrs_case(output + start_sc, txl, amp, sz); } // no DMRS/PTRS in symbol return txl - txl_start; } @@ -477,30 +461,13 @@ static inline void do_txdataF(c16_t **txdataF, const int rb_step = rb_step0==2 && pmi3==pmi && pmi4==pmi ? 4 : rb_step0; const int re_cnt = NR_NB_SC_PER_RB * rb_step; if (pmi == 0) { // unitary Precoding - if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC - if (ant < rel15->nrOfLayers) - memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], - &txdataF_precoding[ant][subCarrier], - re_cnt * sizeof(**txdataF)); - else - memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF)); - } else { // RB does cross DC - const int neg_length = symbol_sz - subCarrier; - const int pos_length = re_cnt - neg_length; - if (ant < rel15->nrOfLayers) { - memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], - &txdataF_precoding[ant][subCarrier], - neg_length * sizeof(**txdataF)); - memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[ant], pos_length * sizeof(**txdataF)); - } else { - memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF)); - memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF)); - } - } + if (ant < rel15->nrOfLayers) + memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + &txdataF_precoding[ant][subCarrier], + re_cnt * sizeof(**txdataF)); + else + memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF)); subCarrier += re_cnt; - if (subCarrier >= symbol_sz) { - subCarrier -= symbol_sz; - } } else { // non-unitary Precoding AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n"); // get the precoding matrix weights: @@ -514,38 +481,21 @@ static inline void do_txdataF(c16_t **txdataF, "Number of layers %d doesn't match to the one in precoding matrix %d\n", rel15->nrOfLayers, pmi_pdu->numLayers); - if ((subCarrier + re_cnt) < symbol_sz) { // within ofdm_symbol_size, use SIMDe - nr_layer_precoder_simd(rel15->nrOfLayers, - symbol_sz, - txdataF_precoding, - ant, - pmi_pdu, - subCarrier, - re_cnt, - &txdataF[ant][txdataF_offset_per_symbol]); - subCarrier += re_cnt; - } else { // crossing ofdm_symbol_size, use simple arithmetic operations - for (int i = 0; i < re_cnt; i++) { - txdataF[ant][txdataF_offset_per_symbol + subCarrier] = - nr_layer_precoder_cm(rel15->nrOfLayers, symbol_sz, txdataF_precoding, ant, pmi_pdu, subCarrier); -#ifdef DEBUG_DLSCH_MAPPING - printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n", - ant, - l_symbol, - subCarrier, - txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].r, - txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].i); -#endif - if (++subCarrier >= symbol_sz) { - subCarrier -= symbol_sz; - } - } - } // else{ // crossing ofdm_symbol_size, use simple arithmetic operations + nr_layer_precoder_simd(rel15->nrOfLayers, + symbol_sz, + txdataF_precoding, + ant, + pmi_pdu, + subCarrier, + re_cnt, + &txdataF[ant][txdataF_offset_per_symbol]); + subCarrier += re_cnt; } // else { // non-unitary Precoding rb += rb_step; } // RB loop: while(rb < rel15->rbSize) } + static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int slot) { const int16_t amp = gNB->TX_AMP; @@ -641,9 +591,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC start_meas(&gNB->dlsch_pdsch_generation_stats); /// Resource mapping // Non interleaved VRB to PRB mapping - uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart + rel15->BWPStart) * NR_NB_SC_PER_RB; - if (start_sc >= symbol_sz) - start_sc -= symbol_sz; + uint16_t start_sc = (rel15->rbStart + rel15->BWPStart) * NR_NB_SC_PER_RB; #ifdef DEBUG_DLSCH_MAPPING printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %d,nb_layers %d)\n", diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 159e040d11..4acda03b91 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -71,7 +71,7 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, /// Resource mapping // PBCH DMRS are mapped within the SSB block on every fourth subcarrier starting from nushift of symbols 1, 2, 3 ///symbol 1 [0+nushift:4:236+nushift] -- 60 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + k = frame_parms->ssb_start_subcarrier + nushift; l = ssb_start_symbol + 1; for (int m = 0; m < 60; m++) { @@ -80,13 +80,10 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, #endif txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[m], amp, 15); k+=4; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 2 [0+u:4:44+nushift ; 192+nu:4:236+nushift] -- 24 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + k = frame_parms->ssb_start_subcarrier + nushift; l++; for (int m = 60; m < 84; m++) { @@ -100,13 +97,10 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); #endif k+=(m==71)?148:4; // Jump from 44+nu to 192+nu - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 3 [0+nushift:4:236+nushift] -- 60 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + nushift; + k = frame_parms->ssb_start_subcarrier + nushift; l++; for (int m = 84; m < NR_PBCH_DMRS_LENGTH; m++) { @@ -115,9 +109,6 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, #endif txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[m], amp, 15); k+=4; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } #ifdef DEBUG_PBCH_DMRS @@ -334,7 +325,7 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, nushift = config->cell_config.phy_cell_id.value &3; // PBCH modulated symbols are mapped within the SSB block on symbols 1, 2, 3 excluding the subcarriers used for the PBCH DMRS ///symbol 1 [0:239] -- 180 mod symbols - int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + int k = frame_parms->ssb_start_subcarrier; int l = ssb_start_symbol + 1; int m = 0; int16_t amp = gNB->TX_AMP; @@ -351,13 +342,10 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 2 [0:47 ; 192:239] -- 72 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + k = frame_parms->ssb_start_subcarrier; l++; m=180; @@ -373,16 +361,10 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } k += 144; - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; - m=216; for (int ssb_sc_idx = 192; ssb_sc_idx < 240; ssb_sc_idx++) { @@ -397,13 +379,10 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } ///symbol 3 [0:239] -- 180 mod symbols - k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + k = frame_parms->ssb_start_subcarrier; l++; m=252; @@ -419,9 +398,5 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, k++; m++; } - - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_prs.c b/openair1/PHY/NR_TRANSPORT/nr_prs.c index 207a94447d..87edffdc7d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prs.c @@ -51,9 +51,9 @@ int nr_generate_prs(int slot, c16_t *txdataF, int16_t amp, prs_config_t *prs_cfg else if (prs_cfg->CombSize == 12){ k_prime = k_prime_table[3][symInd]; } - - k = (prs_cfg->REOffset+k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset*12 + frame_parms->first_carrier_offset; - + + k = (prs_cfg->REOffset + k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset * 12; + // QPSK modulation uint32_t *gold = nr_gold_prs(prs_cfg->NPRSID, slot, l); for (int m = 0; m < (12/prs_cfg->CombSize) * prs_cfg->NumRB; m++) { @@ -66,10 +66,7 @@ int nr_generate_prs(int slot, c16_t *txdataF, int16_t amp, prs_config_t *prs_cfg txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_prs[m], amp, 15); k = k + prs_cfg->CombSize; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; - } + } } #ifdef DEBUG_PRS_MAP LOG_M("nr_prs.m", "prs",(int16_t *)&txdataF[prs_cfg->SymbolStart*frame_parms->ofdm_symbol_size],prs_cfg->NumPRSSymbols*frame_parms->ofdm_symbol_size, 1, 1); diff --git a/openair1/PHY/NR_TRANSPORT/nr_pss.c b/openair1/PHY/NR_TRANSPORT/nr_pss.c index 965ac51c21..6b219dba90 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pss.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pss.c @@ -49,8 +49,7 @@ int nr_generate_pss( c16_t *txdataF, /// Resource mapping // PSS occupies a predefined position (subcarriers 56-182, symbol 0) within the SSB block starting from - int k = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; //and - if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; + int k = frame_parms->ssb_start_subcarrier + 56; int l = ssb_start_symbol; @@ -61,9 +60,6 @@ int nr_generate_pss( c16_t *txdataF, // printf("pss: writing position k %d / %d\n",k,frame_parms->ofdm_symbol_size); ((int16_t*)txdataF)[2*(l*frame_parms->ofdm_symbol_size + k)] = (((int16_t)amp) * d_pss) >> 15; k++; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } #ifdef NR_PSS_DEBUG diff --git a/openair1/PHY/NR_TRANSPORT/nr_sss.c b/openair1/PHY/NR_TRANSPORT/nr_sss.c index 45835f8206..71bae9a065 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sss.c +++ b/openair1/PHY/NR_TRANSPORT/nr_sss.c @@ -59,16 +59,13 @@ 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->first_carrier_offset + frame_parms->ssb_start_subcarrier + 56; //and + int k = frame_parms->ssb_start_subcarrier + 56; int l = ssb_start_symbol + 2; 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++; - - if (k >= frame_parms->ofdm_symbol_size) - k-=frame_parms->ofdm_symbol_size; } #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_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 881ce016bc..e24166a5b6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -1619,7 +1619,14 @@ uint8_t nr_tx_rotation_and_ofdm_mod(const uint8_t slot, if (was_symbol_used[i] == false) continue; for (int ap = 0; ap < n_antenna_ports; ap++) { - apply_nr_rotation_TX(frame_parms, txdataF[ap], frame_parms->symbol_rotation[linktype], slot, N_RB, i, 1); + apply_nr_rotation_TX(frame_parms, + txdataF[ap], + false, + frame_parms->symbol_rotation[linktype], + slot, + N_RB, + i, + 1); } } } diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c index 7cc14b385f..a0db67e50d 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_csirs.c @@ -25,7 +25,6 @@ static void csi_rs_resource_mapping(c16_t **dataF, int csi_rs_length, int16_t mod_csi[][csi_rs_length >> 1], int ofdm_symbol_size, - int start_sc, const csi_mapping_parms_t *mapping_parms, int start_rb, int nb_rbs, @@ -43,7 +42,7 @@ static void csi_rs_resource_mapping(c16_t **dataF, int p = s + mapping_parms->j[ji] * gs; // port index for (int kp = 0; kp <= mapping_parms->kprime; kp++) { // loop over frequency resource elements within a group // frequency index of current resource element - int k = (start_sc + (n * NR_NB_SC_PER_RB) + mapping_parms->koverline[ji] + kp) % (ofdm_symbol_size); + int k = ((n * NR_NB_SC_PER_RB) + mapping_parms->koverline[ji] + kp); // wf according to tables 7.4.5.3-2 to 7.4.5.3-5 int wf = kp == 0 ? 1 : (-2 * (s % 2) + 1); int na = n * alpha; @@ -625,7 +624,6 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, frame_parms->N_RB_DL << 4, mod_csi, frame_parms->ofdm_symbol_size, - frame_parms->first_carrier_offset, phy_csi_parms, start_rb, nr_of_rbs, diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index 01b6fe7389..20ca99f0c4 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -217,8 +217,6 @@ void nr_feptx(void *arg) int startSymbol = feptx->startSymbol; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; int numSymbols = feptx->numSymbols; - int numSamples = feptx->numSymbols * fp->ofdm_symbol_size; - int txdataF_offset = startSymbol * fp->ofdm_symbol_size; int tx_idx = aa + bb * ru->nb_tx; @@ -232,11 +230,17 @@ void nr_feptx(void *arg) } // If there is no digital beamforming we just need to copy the data to RU - if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) - memcpy((void *)&ru->common.txdataF_BF[tx_idx][txdataF_offset], - (void *)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset], - numSamples * sizeof(int32_t)); - else { + if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) { + // FFT shift + const NR_DL_FRAME_PARMS *fp = &ru->gNB_list[0]->frame_parms; + fft_shift(ru->gNB_list[0]->common_vars.txdataF[bb][aa], + fp->ofdm_symbol_size, + fp->N_RB_DL, + (c16_t *)ru->common.txdataF_BF[tx_idx], + fp->ofdm_symbol_size, + startSymbol, + numSymbols); + } else { AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n"); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 80f96e1f43..629d9cc406 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -320,6 +320,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, if (gNB->phase_comp) { apply_nr_rotation_TX(fp, gNB->common_vars.txdataF[i][aa], + true, fp->symbol_rotation[0], slot, fp->N_RB_DL, diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index aa9ebccde8..2cdaa4143e 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1141,9 +1141,17 @@ int main(int argc, char **argv) //TODO: loop over slots for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { - + c16_t fft_in_buff[frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot] __attribute__((aligned(64))); + memset(fft_in_buff, 0, sizeof(fft_in_buff)); if (cyclic_prefix_type == 1) { - PHY_ofdm_mod((int *)gNB->common_vars.txdataF[0][aa], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 12); + PHY_ofdm_mod((int *)fft_in_buff, (int *)&txdata[aa][slot_offset], frame_parms->ofdm_symbol_size, 12, @@ -1154,7 +1162,14 @@ int main(int argc, char **argv) for (int i = 0; i < 14; i++) { was_symbol_used[i] = true; } - nr_normal_prefix_mod(gNB->common_vars.txdataF[0][aa], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 14); + nr_normal_prefix_mod(fft_in_buff, &txdata[aa][slot_offset], 14, frame_parms, diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index cad3012400..a828db184d 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -525,17 +525,28 @@ int main(int argc, char **argv) nr_common_signal_procedures (gNB,frame,slot, &ssb_pdu[i]); int samp = get_samples_slot_timestamp(frame_parms, slot); - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + for (aa = 0; aa < gNB->frame_parms.nb_antennas_tx; aa++) { + c16_t fft_in_buff[frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot] __attribute__((aligned(64))); + memset(fft_in_buff, 0, sizeof(fft_in_buff)); if (cyclic_prefix_type == 1) { apply_nr_rotation_TX(frame_parms, gNB->common_vars.txdataF[0][aa], + true, frame_parms->symbol_rotation[0], slot, frame_parms->N_RB_DL, 0, 12); - PHY_ofdm_mod((int *)gNB->common_vars.txdataF[0][aa], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 12); + + PHY_ofdm_mod((int *)fft_in_buff, (int *)&txdata[aa][samp], frame_parms->ofdm_symbol_size, 12, @@ -544,21 +555,30 @@ int main(int argc, char **argv) } else { apply_nr_rotation_TX(frame_parms, gNB->common_vars.txdataF[0][aa], + true, frame_parms->symbol_rotation[0], slot, frame_parms->N_RB_DL, 0, 14); - PHY_ofdm_mod((int *)gNB->common_vars.txdataF[0][aa], - (int*)&txdata[aa][samp], + fft_shift(gNB->common_vars.txdataF[0][aa], + frame_parms->ofdm_symbol_size, + frame_parms->N_RB_DL, + fft_in_buff, + frame_parms->ofdm_symbol_size, + 0, + 14); + + PHY_ofdm_mod((int *)fft_in_buff, + (int *)&txdata[aa][samp], frame_parms->ofdm_symbol_size, 1, frame_parms->nb_prefix_samples0, CYCLIC_PREFIX); - PHY_ofdm_mod((int *)&gNB->common_vars.txdataF[0][aa][frame_parms->ofdm_symbol_size], - (int*)&txdata[aa][samp + frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size], + PHY_ofdm_mod((int *)fft_in_buff + frame_parms->ofdm_symbol_size, + (int *)&txdata[aa][samp + frame_parms->nb_prefix_samples0 + frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 13, frame_parms->nb_prefix_samples, diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 7f858219ac..d7b39b307b 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -612,21 +612,6 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) int num_totalRB = p_prbMapElm->nRBSize; int start_totalRB = p_prbMapElm->nRBStart; - int pos_len = 0; - int neg_len = 0; - - if (start_totalRB < (num_totalRB >> 1)) // there are PRBs left of DC - neg_len = min((num_totalRB * 6) - (start_totalRB * 12), num_totalRB * N_SC_PER_PRB); - pos_len = (num_totalRB * N_SC_PER_PRB) - neg_len; - // Calculation of the pointer for the section in the buffer. - // start of positive frequency component - uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((start_totalRB * N_SC_PER_PRB) - (num_totalRB * 6)) : 0]; - // start of negative frequency component - uint16_t *src2 = (uint16_t *)&pos[(start_totalRB * N_SC_PER_PRB) + fftsize - (num_totalRB * 6)]; - - uint32_t local_src[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64))); - memcpy((void *)local_src, (void *)src2, neg_len * 4); - memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4); if (ptr && pos) { u8dptr = (uint8_t *)ptr; int16_t payload_len = 0; @@ -662,26 +647,33 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) } uint16_t *dst16 = (uint16_t *)dst; + // Start of this section + int32_t *pos_start = pos + (start_totalRB + startRB) * N_SC_PER_PRB; + if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) { payload_len = numRB * N_SC_PER_PRB * 4L; /* convert to Network order */ // NOTE: ggc 11 knows how to generate AVX2 for this! for (idx = 0; idx < (numRB * N_SC_PER_PRB) * 2; idx++) - ((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx + startRB * N_SC_PER_PRB * 2]); + ((uint16_t *)dst16)[idx] = htons(((uint16_t *)pos_start)[idx]); } else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { payload_len = (3 * p_prbMapElm->iqWidth + 1) * numRB; + /* Although arm intrinsics natively handle unaligned memory + access, we use a 64 byte aligned input here for maximum + performance. So the src_compr buffer is used for both x86 and arm. + */ + uint32_t src_compr[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64))); + + /* Copy from txdataF with current symbol's PRB start (nRBStart) + + current section's PRB start (UP_nPRBStart) */ + memcpy(src_compr, pos_start, (numRB * N_SC_PER_PRB) * sizeof(*pos_start)); + #if defined(__i386__) || defined(__x86_64__) struct xranlib_compress_request bfp_com_req = {}; struct xranlib_compress_response bfp_com_rsp = {}; - uint32_t src_compr[num_totalRB * N_SC_PER_PRB] __attribute__((aligned(64))); - if (numRB == num_totalRB) { - bfp_com_req.data_in = (int16_t *)local_src; - } else { - memcpy(src_compr, local_src + (startRB * N_SC_PER_PRB), (numRB * N_SC_PER_PRB) * sizeof(*local_src)); - bfp_com_req.data_in = (int16_t *)src_compr; - } + bfp_com_req.data_in = (int16_t *)src_compr; bfp_com_req.numRBs = numRB; bfp_com_req.len = payload_len; @@ -693,7 +685,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp); #elif defined(__arm__) || defined(__aarch64__) - armral_bfp_compression(p_prbMapElm->iqWidth, numRB, (int16_t *)(local_src + startRB * N_SC_PER_PRB), (int8_t *)dst); + armral_bfp_compression(p_prbMapElm->iqWidth, numRB, (int16_t *)src_compr, (int8_t *)dst); #else AssertFatal(1 == 0, "BFP compression not supported on this architecture"); #endif @@ -950,7 +942,6 @@ int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t t const struct xran_fh_init *fh_init = get_xran_fh_init(); const struct xran_fh_config *fh_cfg = get_xran_fh_config(0); - int nPRBs = fh_cfg->nDLRBs; int fftsize = 1 << fh_cfg->nDLFftSize; int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports; int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports; @@ -1105,36 +1096,32 @@ int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t t } uint16_t *dst16 = (uint16_t *)dst; - int pos_len = 0; - int neg_len = 0; - - if (p_prbMapElm->UP_nRBStart < (nPRBs >> 1)) // there are PRBs left of DC - neg_len = min((nPRBs * 6) - (p_prbMapElm->UP_nRBStart * 12), p_prbMapElm->UP_nRBSize * N_SC_PER_PRB); - pos_len = (p_prbMapElm->UP_nRBSize * N_SC_PER_PRB) - neg_len; - // Calculation of the pointer for the section in the buffer. - // start of positive frequency component - uint16_t *src1 = (uint16_t *)&pos[(neg_len == 0) ? ((p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) - (nPRBs * 6)) : 0]; - // start of negative frequency component - uint16_t *src2 = (uint16_t *)&pos[(p_prbMapElm->UP_nRBStart * N_SC_PER_PRB) + fftsize - (nPRBs * 6)]; - - uint32_t local_src[p_prbMapElm->UP_nRBSize * N_SC_PER_PRB] __attribute__((aligned(64))); - memcpy((void *)local_src, (void *)src2, neg_len * 4); - memcpy((void *)&local_src[neg_len], (void *)src1, pos_len * 4); + int32_t *pos_start = pos + p_prbMapElm->UP_nRBStart * N_SC_PER_PRB; + uint32_t numPrb = p_prbMapElm->UP_nRBSize; if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_NONE) { - payload_len = p_prbMapElm->UP_nRBSize * N_SC_PER_PRB * 4L; + payload_len = numPrb * N_SC_PER_PRB * 4L; /* convert to Network order */ // NOTE: ggc 11 knows how to generate AVX2 for this! - for (idx = 0; idx < (pos_len + neg_len) * 2; idx++) - ((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx]); + for (idx = 0; idx < numPrb * N_SC_PER_PRB * 2; idx++) + ((uint16_t *)dst16)[idx] = htons(((uint16_t *)pos_start)[idx]); } else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { - payload_len = (3 * p_prbMapElm->iqWidth + 1) * p_prbMapElm->UP_nRBSize; + payload_len = (3 * p_prbMapElm->iqWidth + 1) * numPrb; + /* Although arm intrinsics natively handle unaligned memory + access, we use a 64 byte aligned input here for maximum + performance. So the src_compr buffer is used for both x86 and arm. + */ + uint32_t src_compr[numPrb * N_SC_PER_PRB] __attribute__((aligned(64))); + + /* Copy from txdataF with current symbol's PRB start (nRBStart) + + current section's PRB start (UP_nPRBStart) */ + memcpy(src_compr, pos_start, (numPrb * N_SC_PER_PRB) * sizeof(*pos_start)); #if defined(__i386__) || defined(__x86_64__) struct xranlib_compress_request bfp_com_req = {}; struct xranlib_compress_response bfp_com_rsp = {}; - bfp_com_req.data_in = (int16_t *)local_src; - bfp_com_req.numRBs = p_prbMapElm->UP_nRBSize; + bfp_com_req.data_in = (int16_t *)src_compr; + bfp_com_req.numRBs = numPrb; bfp_com_req.len = payload_len; bfp_com_req.compMethod = p_prbMapElm->compMethod; bfp_com_req.iqWidth = p_prbMapElm->iqWidth; @@ -1144,7 +1131,7 @@ int xran_fh_tx_send_slot_BySymbol(ru_info_t *ru, int frame, int slot, uint64_t t xranlib_compress_avx512(&bfp_com_req, &bfp_com_rsp); #elif defined(__arm__) || defined(__aarch64__) - armral_bfp_compression(p_prbMapElm->iqWidth, p_prbMapElm->UP_nRBSize, (int16_t *)local_src, (int8_t *)dst); + armral_bfp_compression(p_prbMapElm->iqWidth, numPrb, (int16_t *)src_compr, (int8_t *)dst); #else AssertFatal(1 == 0, "BFP compression not supported on this architecture"); #endif From 5d9f7b41c1c8a85c96f44fa8abe0f9a7aec60132 Mon Sep 17 00:00:00 2001 From: Rakesh BB Date: Wed, 4 Mar 2026 06:37:45 +0000 Subject: [PATCH 15/30] XNAP: add logging support and update ASN.1 runtime sources - Add XNAP component to the logging framework in log.h - Introduce LEGACY_XNAP log message definitions (INFO, ERROR, WARNING, DEBUG, TRACE) in T_messages.txt for tracing and debugging XNAP procedures - Update xnap_R16.2.0.cmake formatting for consistency - Add missing ASN.1 runtime sources required by XNAP (e.g. asn_codecs_prim_xer.c, BIT_STRING_print.c, BIT_STRING_rfill.c, etc.) --- common/utils/LOG/log.h | 1 + common/utils/T/T_messages.txt | 21 +++ .../XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake | 124 +++++++++++++++++- 3 files changed, 141 insertions(+), 5 deletions(-) diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h index 837c6897a6..b8ccedffbe 100644 --- a/common/utils/LOG/log.h +++ b/common/utils/LOG/log.h @@ -162,6 +162,7 @@ static const char *const flag_name[] = {FOREACH_FLAG(FLAG_TEXT) ""}; COMP_DEF(USIM, log) \ COMP_DEF(F1U, ) \ COMP_DEF(X2AP, ) \ + COMP_DEF(XNAP, ) \ COMP_DEF(M2AP, ) \ COMP_DEF(M3AP, ) \ COMP_DEF(NGAP, ) \ diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index 818b30b7d0..432ad30262 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -628,6 +628,27 @@ ID = LEGACY_X2AP_TRACE GROUP = ALL:LEGACY_X2AP:LEGACY_GROUP_TRACE:LEGACY FORMAT = string,log +ID = LEGACY_XNAP_INFO + DESC = XNAP legacy logs - info level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_INFO:LEGACY + FORMAT = string,log +ID = LEGACY_XNAP_ERROR + DESC = XNAP legacy logs - error level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_ERROR:LEGACY + FORMAT = string,log +ID = LEGACY_XNAP_WARNING + DESC = XNAP legacy logs - warning level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_WARNING:LEGACY + FORMAT = string,log +ID = LEGACY_XNAP_DEBUG + DESC = XNAP legacy logs - debug level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_DEBUG:LEGACY + FORMAT = string,log +ID = LEGACY_XNAP_TRACE + DESC = XNAP legacy logs - trace level + GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_TRACE:LEGACY + FORMAT = string,log + ID = LEGACY_M2AP_INFO DESC = M2AP legacy logs - info level GROUP = ALL:LEGACY_M2AP:LEGACY_GROUP_INFO:LEGACY diff --git a/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake b/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake index cb0c762983..4a46649449 100644 --- a/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake +++ b/openair2/XNAP/MESSAGES/ASN1/xnap_R16.2.0.cmake @@ -1,4 +1,4 @@ -set( XNAP_GRAMMAR ASN1/xnap_R16.2.0.asn) +set(XNAP_GRAMMAR ASN1/xnap_R16.2.0.asn) set(xnap_source ANY.c @@ -9,6 +9,7 @@ set(xnap_source asn_application.c asn_bit_data.c asn_codecs_prim.c + asn_codecs_prim_xer.c asn_internal.c asn_random_fill.c asn_SEQUENCE_OF.c @@ -16,20 +17,73 @@ set(xnap_source ber_tlv_length.c ber_tlv_tag.c BIT_STRING.c + BIT_STRING_print.c + BIT_STRING_rfill.c + BIT_STRING_uper.c + BIT_STRING_xer.c constraints.c constr_CHOICE.c + constr_CHOICE_aper.c + constr_CHOICE_rfill.c + constr_CHOICE_print.c + constr_CHOICE_uper.c + constr_CHOICE_xer.c constr_SEQUENCE.c + constr_SEQUENCE_aper.c constr_SEQUENCE_OF.c + constr_SEQUENCE_OF_aper.c + constr_SEQUENCE_OF_uper.c + constr_SEQUENCE_OF_xer.c + constr_SEQUENCE_print.c + constr_SEQUENCE_rfill.c + constr_SEQUENCE_uper.c + constr_SEQUENCE_xer.c constr_SET_OF.c + constr_SET_OF_aper.c + constr_SET_OF_print.c + constr_SET_OF_rfill.c + constr_SET_OF_uper.c + constr_SET_OF_xer.c constr_TYPE.c INTEGER.c + INTEGER_aper.c + INTEGER_print.c + INTEGER_rfill.c + INTEGER_uper.c + INTEGER_xer.c Makefile.am.libasncodec NativeEnumerated.c + NativeEnumerated_aper.c + NativeEnumerated_uper.c + NativeEnumerated_xer.c NativeInteger.c + NativeInteger_aper.c + NativeInteger_print.c + NativeInteger_rfill.c + NativeInteger_uper.c + NativeInteger_xer.c NULL.c + NULL_aper.c + NULL_print.c + NULL_rfill.c + NULL_uper.c + NULL_xer.c OBJECT_IDENTIFIER.c + OBJECT_IDENTIFIER_print.c + OBJECT_IDENTIFIER_rfill.c + OBJECT_IDENTIFIER_xer.c OCTET_STRING.c + OCTET_STRING_aper.c + OCTET_STRING_print.c + OCTET_STRING_rfill.c + OCTET_STRING_uper.c + OCTET_STRING_xer.c OPEN_TYPE.c + OPEN_TYPE_aper.c + OPEN_TYPE_uper.c + OPEN_TYPE_xer.c + per_opentype.c + per_encoder.c VisibleString.c xer_decoder.c xer_encoder.c @@ -819,14 +873,22 @@ set(xnap_source XNAP_XnUAddressIndication.c XNAP_XnUAddressInfoperPDUSession-Item.c XNAP_XnUAddressInfoperPDUSession-List.c + uper_encoder.c + uper_opentype.c + uper_support.c ) set(xnap_headers ANY.h + aper_decoder.h + aper_encoder.h + aper_opentype.h + aper_support.h asn_application.h asn_bit_data.h asn_codecs.h asn_codecs_prim.h + asn_codecs_prim_xer.h asn_internal.h asn_ioc.h asn_random_fill.h @@ -836,23 +898,72 @@ set(xnap_headers ber_tlv_length.h ber_tlv_tag.h BIT_STRING.h + BIT_STRING_print.h + BIT_STRING_rfill.h + BIT_STRING_uper.h + BIT_STRING_xer.h constraints.h constr_CHOICE.h + constr_CHOICE_aper.h + constr_CHOICE_print.h + constr_CHOICE_rfill.h + constr_CHOICE_uper.h + constr_CHOICE_xer.h constr_SEQUENCE.h + constr_SEQUENCE_aper.h constr_SEQUENCE_OF.h + constr_SEQUENCE_OF_aper.h + constr_SEQUENCE_OF_uper.h + constr_SEQUENCE_OF_xer.h + constr_SEQUENCE_print.h + constr_SEQUENCE_rfill.h + constr_SEQUENCE_uper.h + constr_SEQUENCE_xer.h constr_SET_OF.h + constr_SET_OF_aper.h + constr_SET_OF_print.h + constr_SET_OF_rfill.h + constr_SET_OF_uper.h + constr_SET_OF_xer.h constr_TYPE.h INTEGER.h + INTEGER_aper.h + INTEGER_print.h + INTEGER_rfill.h + INTEGER_uper.h + INTEGER_xer.h NativeEnumerated.h + NativeEnumerated_aper.h + NativeEnumerated_uper.h + NativeEnumerated_xer.h NativeInteger.h + NativeInteger_aper.h + NativeInteger_print.h + NativeInteger_rfill.h + NativeInteger_xer.h + NativeInteger_uper.h NULL.h + NULL_aper.h + NULL_print.h + NULL_rfill.h + NULL_uper.h + NULL_xer.h OBJECT_IDENTIFIER.h + OBJECT_IDENTIFIER_print.h + OBJECT_IDENTIFIER_rfill.h + OBJECT_IDENTIFIER_xer.h OCTET_STRING.h + OCTET_STRING_aper.h + OCTET_STRING_print.h + OCTET_STRING_rfill.h + OCTET_STRING_uper.h + OCTET_STRING_xer.h OPEN_TYPE.h - aper_decoder.h - aper_encoder.h - aper_opentype.h - aper_support.h + OPEN_TYPE_aper.h + OPEN_TYPE_uper.h + OPEN_TYPE_xer.h + per_encoder.h + per_opentype.h VisibleString.h xer_decoder.h xer_encoder.h @@ -1643,5 +1754,8 @@ set(xnap_headers XNAP_XnUAddressIndication.h XNAP_XnUAddressInfoperPDUSession-Item.h XNAP_XnUAddressInfoperPDUSession-List.h + uper_encoder.h + uper_opentype.h + uper_support.h ) From 08b454bd15b5841a983a0553f65aa87a209d0593 Mon Sep 17 00:00:00 2001 From: Rakesh BB Date: Wed, 4 Mar 2026 07:04:32 +0000 Subject: [PATCH 16/30] XNAP: Introduce XnAP library framework and add encode/decode, unit test for Xn Setup Request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add initial XnAP library structure under openair2/XNAP/lib - Implement common XnAP helper utilities (xnap_lib_common) - Add gNB interface management module for Xn Setup procedures - Introduce XnAP message type definitions in xnap_messages_types.h - Integrate XnAP library into build system (CMakeLists.txt) - Add standalone XnAP library unit test (xnap_lib_test) - Implement encoder, decoder + test for Xn Setup Request Xn Setup Request (3GPP TS 38.423v16.2.0 §9.1.3.1) - Global NG-RAN Node ID (M) - TAI Support List (M) - AMF Region Information (M) - Extend conversions.h with MACRO_BIT_STRING_TO_GNB_ID utility Co-authored-by: Sreeshma Shiv --- CMakeLists.txt | 11 + openair2/COMMON/xnap_messages_types.h | 65 +++++ openair2/XNAP/CMakeLists.txt | 12 +- openair2/XNAP/lib/CMakeLists.txt | 10 + .../XNAP/lib/xnap_gNB_interface_management.c | 246 ++++++++++++++++++ .../XNAP/lib/xnap_gNB_interface_management.h | 37 +++ openair2/XNAP/lib/xnap_lib_common.c | 61 +++++ openair2/XNAP/lib/xnap_lib_common.h | 60 +++++ openair2/XNAP/lib/xnap_lib_includes.h | 42 +++ openair2/XNAP/tests/CMakeLists.txt | 9 + openair2/XNAP/tests/xnap_lib_test.c | 176 +++++++++++++ openair3/UTILS/conversions.h | 10 + 12 files changed, 734 insertions(+), 5 deletions(-) create mode 100644 openair2/COMMON/xnap_messages_types.h create mode 100644 openair2/XNAP/lib/CMakeLists.txt create mode 100644 openair2/XNAP/lib/xnap_gNB_interface_management.c create mode 100644 openair2/XNAP/lib/xnap_gNB_interface_management.h create mode 100644 openair2/XNAP/lib/xnap_lib_common.c create mode 100644 openair2/XNAP/lib/xnap_lib_common.h create mode 100644 openair2/XNAP/lib/xnap_lib_includes.h create mode 100644 openair2/XNAP/tests/CMakeLists.txt create mode 100644 openair2/XNAP/tests/xnap_lib_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b8a1b3a082..1cb3e09736 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -517,6 +517,17 @@ add_library(x2ap target_link_libraries(x2ap PUBLIC asn1_x2ap) target_link_libraries(x2ap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +#XNAP +############## +set(XNAP_DIR ${OPENAIR2_DIR}/XNAP) +add_library(xnap + ${XNAP_DIR}/xnap_common.c + ) +target_include_directories(xnap PUBLIC XNAP_DIR) +target_link_libraries(xnap PUBLIC asn1_xnap) +target_link_libraries(xnap PRIVATE nr_rrc xnap_lib) +target_include_directories(xnap PRIVATE ${XNAP_DIR}/lib) + # F1AP ############## set(F1AP_DIR ${OPENAIR2_DIR}/F1AP) diff --git a/openair2/COMMON/xnap_messages_types.h b/openair2/COMMON/xnap_messages_types.h new file mode 100644 index 0000000000..1080e5fb1b --- /dev/null +++ b/openair2/COMMON/xnap_messages_types.h @@ -0,0 +1,65 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef XNAP_MESSAGES_TYPES_H_ +#define XNAP_MESSAGES_TYPES_H_ + +#include "common/5g_platform_types.h" + +typedef struct { + // PLMN Identity + plmn_id_t plmn; + // Number of supported S-NSSAIs + uint16_t num_nssai; + // List of supported S-NSSAIs + nssai_t *nssai; +} xnap_plmn_support_t; + +typedef struct { + // Tracking Area Code + uint32_t tac; + // Number of supported PLMNs + uint8_t num_plmn; + // List of supported PLMNs + xnap_plmn_support_t *plmn_support; +} xnap_tai_support_t; + +typedef struct { + // PLMN Identity + plmn_id_t plmn; + // AMF Region Identifier + uint8_t amf_region_id; +} xnap_amf_region_info_t; + +/* 3GPP TS 38.423 9.1.3.1 – Xn Setup Request */ +typedef struct { + // Global NG-RAN Node ID (gNB_id+plmn) (M) + uint32_t gNB_id; + plmn_id_t plmn; + // TAI Support List (M) + uint16_t num_tai; + xnap_tai_support_t *tai_support; + // AMF Region Information (M) + uint8_t num_amf_regions; + xnap_amf_region_info_t *amf_region_info; +} xnap_setup_req_t; + +#endif /* XNAP_MESSAGES_TYPES_H_ */ diff --git a/openair2/XNAP/CMakeLists.txt b/openair2/XNAP/CMakeLists.txt index d003732d8a..10576f8403 100644 --- a/openair2/XNAP/CMakeLists.txt +++ b/openair2/XNAP/CMakeLists.txt @@ -1,7 +1,9 @@ +add_subdirectory(lib) add_subdirectory(MESSAGES) -add_library(xnap xnap_common.c) -target_link_libraries(xnap - PUBLIC asn1_xnap - PRIVATE nr_rrc) -target_include_directories(xnap PUBLIC ${CMAKE_CURRENT_DIR}) + +if(ENABLE_TESTS) + add_subdirectory(tests) +endif() + + diff --git a/openair2/XNAP/lib/CMakeLists.txt b/openair2/XNAP/lib/CMakeLists.txt new file mode 100644 index 0000000000..5e4d5124b0 --- /dev/null +++ b/openair2/XNAP/lib/CMakeLists.txt @@ -0,0 +1,10 @@ +add_library(xnap_lib OBJECT + xnap_lib_common.c + xnap_gNB_interface_management.c +) +target_link_libraries(xnap_lib PRIVATE asn1_xnap ds) + +if(ENABLE_TESTS) + target_compile_definitions(xnap_lib PRIVATE ENABLE_TESTS) +endif() + diff --git a/openair2/XNAP/lib/xnap_gNB_interface_management.c b/openair2/XNAP/lib/xnap_gNB_interface_management.c new file mode 100644 index 0000000000..b374580851 --- /dev/null +++ b/openair2/XNAP/lib/xnap_gNB_interface_management.c @@ -0,0 +1,246 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* + * \brief xnap interface handler procedures for gNB + */ + +#include "xnap_gNB_interface_management.h" +#include "xnap_lib_common.h" +#include "xnap_lib_includes.h" + +/** + * @brief XnAP Setup Request encoding + */ +XNAP_XnAP_PDU_t *encode_xn_setup_request(const xnap_setup_req_t *msg) +{ + XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* PDU type */ + pdu->present = XNAP_XnAP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = XNAP_ProcedureCode_id_xnSetup; + initMsg->criticality = XNAP_Criticality_reject; + initMsg->value.present = XNAP_InitiatingMessage__value_PR_XnSetupRequest; + + XNAP_XnSetupRequest_t *out = &initMsg->value.choice.XnSetupRequest; + + /* Global NG-RAN Node ID (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupRequest_IEs_t, ieC1); + ieC1->id = XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID; + ieC1->criticality = XNAP_Criticality_reject; + ieC1->value.present = XNAP_XnSetupRequest_IEs__value_PR_GlobalNG_RANNode_ID; + + XNAP_GlobalNG_RANNode_ID_t *global = &ieC1->value.choice.GlobalNG_RANNode_ID; + global->present = XNAP_GlobalNG_RANNode_ID_PR_gNB; + asn1cCalloc(global->choice.gNB, gnb); + + MCC_MNC_TO_PLMNID(msg->plmn.mcc, msg->plmn.mnc, msg->plmn.mnc_digit_length, &gnb->plmn_id); + gnb->gnb_id.present = XNAP_GNB_ID_Choice_PR_gnb_ID; + MACRO_GNB_ID_TO_BIT_STRING(msg->gNB_id, &gnb->gnb_id.choice.gnb_ID); + + /* TAI Support List (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupRequest_IEs_t, ieC2); + ieC2->id = XNAP_ProtocolIE_ID_id_TAISupport_list; + ieC2->criticality = XNAP_Criticality_reject; + ieC2->value.present = XNAP_XnSetupRequest_IEs__value_PR_TAISupport_List; + + for (int i = 0; i < msg->num_tai; i++) { + asn1cSequenceAdd(ieC2->value.choice.TAISupport_List.list, XNAP_TAISupport_Item_t, taiItem); + INT24_TO_OCTET_STRING(msg->tai_support[i].tac, &taiItem->tac); + + for (int j = 0; j < msg->tai_support[i].num_plmn; j++) { + const xnap_plmn_support_t *plmn = &msg->tai_support[i].plmn_support[j]; + asn1cSequenceAdd(taiItem->broadcastPLMNs.list, XNAP_BroadcastPLMNinTAISupport_Item_t, plmnItem); + MCC_MNC_TO_PLMNID(plmn->plmn.mcc, plmn->plmn.mnc, plmn->plmn.mnc_digit_length, &plmnItem->plmn_id); + + for (int k = 0; k < plmn->num_nssai; k++) { + asn1cSequenceAdd(plmnItem->tAISliceSupport_List.list, XNAP_S_NSSAI_t, nssai); + INT8_TO_OCTET_STRING(plmn->nssai[k].sst, &nssai->sst); + if (plmn->nssai[k].sd) { asn1cCalloc(nssai->sd, sd); INT24_TO_OCTET_STRING(plmn->nssai[k].sd, sd); } + } + } + } + + /* AMF Region Information (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupRequest_IEs_t, ieC3); + ieC3->id = XNAP_ProtocolIE_ID_id_AMF_Region_Information; + ieC3->criticality = XNAP_Criticality_reject; + ieC3->value.present = XNAP_XnSetupRequest_IEs__value_PR_AMF_Region_Information; + + for (int i = 0; i < msg->num_amf_regions; i++) { + const xnap_amf_region_info_t *amf = &msg->amf_region_info[i]; + asn1cSequenceAdd(ieC3->value.choice.AMF_Region_Information.list, XNAP_GlobalAMF_Region_Information_t, amfItem); + MCC_MNC_TO_PLMNID(amf->plmn.mcc, amf->plmn.mnc, amf->plmn.mnc_digit_length, &amfItem->plmn_ID); + INT8_TO_OCTET_STRING(amf->amf_region_id, &amfItem->amf_region_id); + } + + return pdu; +} + +/** + * @brief XnAP Setup Request decoding + */ +bool decode_xn_setup_request(xnap_setup_req_t *out, const XNAP_XnAP_PDU_t *pdu) +{ + /* Check presence of message type */ + _EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_initiatingMessage); + AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL"); + _EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, XNAP_ProcedureCode_id_xnSetup); + _EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, XNAP_InitiatingMessage__value_PR_XnSetupRequest); + /* XnSetupRequest container */ + XNAP_XnSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.XnSetupRequest; + + XNAP_XnSetupRequest_IEs_t *ie; + /* Check presence of mandatory IEs */ + XNAP_LIB_FIND_IE(XNAP_XnSetupRequest_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID, true); + XNAP_LIB_FIND_IE(XNAP_XnSetupRequest_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_TAISupport_list, true); + XNAP_LIB_FIND_IE(XNAP_XnSetupRequest_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_AMF_Region_Information, true); + + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + AssertError(in->protocolIEs.list.array[i] != NULL, return false, "protocolIEs.list.array[i] is NULL"); + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID: { + /* Global NG-RAN Node ID (M) */ + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupRequest_IEs__value_PR_GlobalNG_RANNode_ID); + XNAP_GlobalNG_RANNode_ID_t *global_id = &ie->value.choice.GlobalNG_RANNode_ID; + AssertError(global_id->present == XNAP_GlobalNG_RANNode_ID_PR_gNB, return false, "Only gNB supported"); + AssertError(global_id->choice.gNB != NULL, return false, "gNB is NULL"); + /* Decode PLMN */ + PLMNID_TO_MCC_MNC(&global_id->choice.gNB->plmn_id, + out->plmn.mcc, + out->plmn.mnc, + out->plmn.mnc_digit_length); + /* Decode gNB ID */ + AssertError(global_id->choice.gNB->gnb_id.present == XNAP_GNB_ID_Choice_PR_gnb_ID, return false, "Unsupported gNB ID choice"); + MACRO_BIT_STRING_TO_GNB_ID(&global_id->choice.gNB->gnb_id.choice.gnb_ID, out->gNB_id); + } break; + + case XNAP_ProtocolIE_ID_id_TAISupport_list: { + /* TAI Support List (M) */ + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupRequest_IEs__value_PR_TAISupport_List); + int tai_count = ie->value.choice.TAISupport_List.list.count; + out->num_tai = tai_count; + out->tai_support = calloc_or_fail(tai_count, sizeof(*out->tai_support)); + for (int m = 0; m < tai_count; m++) { + XNAP_TAISupport_Item_t *tai_item = ie->value.choice.TAISupport_List.list.array[m]; + /* TAC */ + OCTET_STRING_TO_INT24(&tai_item->tac, out->tai_support[m].tac); + /* PLMN list */ + out->tai_support[m].num_plmn = tai_item->broadcastPLMNs.list.count; + out->tai_support[m].plmn_support = calloc_or_fail(out->tai_support[m].num_plmn, sizeof(*out->tai_support[m].plmn_support)); + for (int j = 0; j < out->tai_support[m].num_plmn; j++) { + XNAP_BroadcastPLMNinTAISupport_Item_t *plmn_item = tai_item->broadcastPLMNs.list.array[j]; + xnap_plmn_support_t *plmn = &out->tai_support[m].plmn_support[j]; + PLMNID_TO_MCC_MNC(&plmn_item->plmn_id, + plmn->plmn.mcc, + plmn->plmn.mnc, + plmn->plmn.mnc_digit_length); + /* NSSAI */ + plmn->num_nssai = plmn_item->tAISliceSupport_List.list.count; + plmn->nssai = calloc_or_fail(plmn->num_nssai, sizeof(*plmn->nssai)); + for (int k = 0; k < plmn->num_nssai; k++) { + OCTET_STRING_TO_INT8(&plmn_item->tAISliceSupport_List.list.array[k]->sst, plmn->nssai[k].sst); + if (plmn_item->tAISliceSupport_List.list.array[k]->sd) { + OCTET_STRING_TO_INT24(plmn_item->tAISliceSupport_List.list.array[k]->sd, plmn->nssai[k].sd); + } + } + } + } + } break; + + case XNAP_ProtocolIE_ID_id_AMF_Region_Information: { + /* AMF Region Information (M) */ + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupRequest_IEs__value_PR_AMF_Region_Information); + out->num_amf_regions = ie->value.choice.AMF_Region_Information.list.count; + out->amf_region_info = calloc_or_fail(out->num_amf_regions, sizeof(*out->amf_region_info)); + for (int a = 0; a < out->num_amf_regions; a++) { + XNAP_GlobalAMF_Region_Information_t *amf = ie->value.choice.AMF_Region_Information.list.array[a]; + PLMNID_TO_MCC_MNC(&amf->plmn_ID, + out->amf_region_info[a].plmn.mcc, + out->amf_region_info[a].plmn.mnc, + out->amf_region_info[a].plmn.mnc_digit_length); + OCTET_STRING_TO_INT8(&amf->amf_region_id, out->amf_region_info[a].amf_region_id); + } + } break; + + default: + AssertError(0, return false, "Unknown XnAP IE id %ld\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief XnAP Setup Request main equality check + */ +bool eq_xnap_setup_request(const xnap_setup_req_t *a, const xnap_setup_req_t *b) +{ + _EQ_CHECK_UINT32(a->gNB_id, b->gNB_id); + if (!eq_xnap_plmn(&a->plmn, &b->plmn)) return false; + + _EQ_CHECK_INT(a->num_tai, b->num_tai); + for (int i = 0; i < a->num_tai; i++) { + if (!eq_xnap_tai_support(&a->tai_support[i], &b->tai_support[i])) + return false; + } + + _EQ_CHECK_INT(a->num_amf_regions, b->num_amf_regions); + for (int i = 0; i < a->num_amf_regions; i++) { + if (!eq_xnap_plmn(&a->amf_region_info[i].plmn, &b->amf_region_info[i].plmn)) + return false; + _EQ_CHECK_INT(a->amf_region_info[i].amf_region_id, b->amf_region_info[i].amf_region_id); + } + + return true; +} + +static void free_xnap_plmn_support(xnap_plmn_support_t *plmn_support, uint8_t num_plmn) +{ + if (!plmn_support) return; + for (int i = 0; i < num_plmn; i++) { + free(plmn_support[i].nssai); + } + free(plmn_support); +} + +static void free_xnap_tai_support(xnap_tai_support_t *tai_support, uint16_t num_tai) +{ + if (!tai_support) return; + for (int i = 0; i < num_tai; i++) { + free_xnap_plmn_support(tai_support[i].plmn_support, + tai_support[i].num_plmn); + } + free(tai_support); +} + +/** + * @brief XnAP Setup Request memory management + */ +void free_xnap_setup_request(const xnap_setup_req_t *msg) +{ + DevAssert(msg != NULL); + free_xnap_tai_support(msg->tai_support, msg->num_tai); + free(msg->amf_region_info); +} diff --git a/openair2/XNAP/lib/xnap_gNB_interface_management.h b/openair2/XNAP/lib/xnap_gNB_interface_management.h new file mode 100644 index 0000000000..a4e65d6e00 --- /dev/null +++ b/openair2/XNAP/lib/xnap_gNB_interface_management.h @@ -0,0 +1,37 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef XNAP_GNB_INTERFACE_MANAGEMENT_H_ +#define XNAP_GNB_INTERFACE_MANAGEMENT_H_ + +#include +#include "xnap_messages_types.h" +typedef struct XNAP_XnAP_PDU XNAP_XnAP_PDU_t; + +XNAP_XnAP_PDU_t *encode_xn_setup_request(const xnap_setup_req_t *req); + +bool decode_xn_setup_request(xnap_setup_req_t *req, const XNAP_XnAP_PDU_t *pdu); + +bool eq_xnap_setup_request(const xnap_setup_req_t *a, const xnap_setup_req_t *b); + +void free_xnap_setup_request(const xnap_setup_req_t *msg); + +#endif /* XNAP_GNB_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/XNAP/lib/xnap_lib_common.c b/openair2/XNAP/lib/xnap_lib_common.c new file mode 100644 index 0000000000..9c6a09c80c --- /dev/null +++ b/openair2/XNAP/lib/xnap_lib_common.c @@ -0,0 +1,61 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "xnap_lib_common.h" +#include "common/utils/assertions.h" +#include "common/utils/utils.h" + +bool eq_xnap_plmn(const plmn_id_t *a, const plmn_id_t *b) +{ + _EQ_CHECK_INT(a->mcc, b->mcc); + _EQ_CHECK_INT(a->mnc, b->mnc); + _EQ_CHECK_INT(a->mnc_digit_length, b->mnc_digit_length); + return true; +} + +bool eq_xnap_snssai(const nssai_t *a, const nssai_t *b) +{ + _EQ_CHECK_INT(a->sst, b->sst); + _EQ_CHECK_UINT32(a->sd, b->sd); + return true; +} + +bool eq_xnap_plmn_support(const xnap_plmn_support_t *a, const xnap_plmn_support_t *b) +{ + if (!eq_xnap_plmn(&a->plmn, &b->plmn)) return false; + _EQ_CHECK_INT(a->num_nssai, b->num_nssai); + for (int i = 0; i < a->num_nssai; i++) { + if (!eq_xnap_snssai(&a->nssai[i], &b->nssai[i])) + return false; + } + return true; +} + +bool eq_xnap_tai_support(const xnap_tai_support_t *a, const xnap_tai_support_t *b) +{ + _EQ_CHECK_UINT32(a->tac, b->tac); + _EQ_CHECK_INT(a->num_plmn, b->num_plmn); + for (int i = 0; i < a->num_plmn; i++) { + if (!eq_xnap_plmn_support(&a->plmn_support[i], &b->plmn_support[i])) + return false; + } + return true; +} diff --git a/openair2/XNAP/lib/xnap_lib_common.h b/openair2/XNAP/lib/xnap_lib_common.h new file mode 100644 index 0000000000..cde0accd88 --- /dev/null +++ b/openair2/XNAP/lib/xnap_lib_common.h @@ -0,0 +1,60 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef XNAP_LIB_COMMON_H_ +#define XNAP_LIB_COMMON_H_ + +#include +#include +#include +#include +#include +#include "openair3/UTILS/conversions.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/utils.h" +#include "common/utils/eq_check.h" +#include "xnap_messages_types.h" +#include "xnap_lib_includes.h" + +/* macro to look up XnAP IE. If mandatory and not found, macro will print + * descriptive debug message to stderr and force exit in calling function */ +#define XNAP_LIB_FIND_IE(IE_TYPE, ie, IE_LIST, IE_ID, mandatory) \ + do { \ + ie = NULL; \ + for (IE_TYPE **ptr = (IE_LIST)->array; ptr < &(IE_LIST)->array[(IE_LIST)->count]; ptr++) { \ + if ((*ptr)->id == IE_ID) { \ + ie = *ptr; \ + break; \ + } \ + } \ + if ((mandatory) && (ie == NULL)) { \ + fprintf(stderr, "%s(): could not find XnAP IE " #IE_ID " of type " #IE_TYPE "\n", __func__); \ + return false; \ + } \ + } while (0) + +/* Function Prototypes */ +bool eq_xnap_plmn(const plmn_id_t *a, const plmn_id_t *b); +bool eq_xnap_snssai(const nssai_t *a, const nssai_t *b); +bool eq_xnap_tai_support(const xnap_tai_support_t *a, const xnap_tai_support_t *b); +bool eq_xnap_plmn_support(const xnap_plmn_support_t *a, const xnap_plmn_support_t *b); + +#endif /* XNAP_LIB_COMMON_H_ */ diff --git a/openair2/XNAP/lib/xnap_lib_includes.h b/openair2/XNAP/lib/xnap_lib_includes.h new file mode 100644 index 0000000000..a67919413a --- /dev/null +++ b/openair2/XNAP/lib/xnap_lib_includes.h @@ -0,0 +1,42 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* + * \brief XnAP ASN.1 message definitions generated from specifications + */ + +#ifndef XNAP_LIB_INCLUDES_H +#define XNAP_LIB_INCLUDES_H + +#include "XNAP_XnAP-PDU.h" +#include "XNAP_ProtocolIE-Field.h" +#include "XNAP_InitiatingMessage.h" + +#include "XNAP_GlobalgNB-ID.h" +#include "XNAP_GlobalNG-RANNode-ID.h" +#include "XNAP_GlobalAMF-Region-Information.h" +#include "XNAP_TAISupport-Item.h" +#include "XNAP_S-NSSAI.h" +#include "XNAP_BroadcastPLMNinTAISupport-Item.h" + + +#endif // XNAP_LIB_INCLUDES_H + diff --git a/openair2/XNAP/tests/CMakeLists.txt b/openair2/XNAP/tests/CMakeLists.txt new file mode 100644 index 0000000000..7c6875b887 --- /dev/null +++ b/openair2/XNAP/tests/CMakeLists.txt @@ -0,0 +1,9 @@ +add_executable(xnap_lib_test xnap_lib_test.c) +add_dependencies(tests xnap_lib_test) +add_test(NAME xnap_lib_test COMMAND xnap_lib_test) +target_link_libraries(xnap_lib_test PRIVATE xnap_lib ds LOG) +target_link_libraries(xnap_lib_test PRIVATE asn1_xnap) +target_include_directories(xnap_lib_test PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/openair2/XNAP/tests/xnap_lib_test.c b/openair2/XNAP/tests/xnap_lib_test.c new file mode 100644 index 0000000000..c17f6b4967 --- /dev/null +++ b/openair2/XNAP/tests/xnap_lib_test.c @@ -0,0 +1,176 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* + * \brief Test functions for XnAP encoding/decoding library + */ + +#include +#include +#include +#include +#include "common/utils/assertions.h" +#include "common/utils/utils.h" +#include "xnap_messages_types.h" +#include "openair2/XNAP/lib/xnap_lib_common.h" +#include "openair2/XNAP/lib/xnap_gNB_interface_management.h" + +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + printf("detected error at %s:%d:%s: %s\n", file, line, function, s); + abort(); +} + +/* Helper for ASN.1 Encoding/Decoding loop */ +static XNAP_XnAP_PDU_t *xnap_encode_decode(const XNAP_XnAP_PDU_t *enc_pdu) +{ + //xer_fprint(stdout, &asn_DEF_XNAP_XnAP_PDU, enc_pdu); + DevAssert(enc_pdu != NULL); + char errbuf[1024]; + size_t errlen = sizeof(errbuf); + int ret = asn_check_constraints(&asn_DEF_XNAP_XnAP_PDU, enc_pdu, errbuf, &errlen); + AssertFatal(ret == 0, "asn_check_constraints() failed: %s\n", errbuf); + + uint8_t msgbuf[16384]; + // 1. Encode + asn_enc_rval_t enc = aper_encode_to_buffer(&asn_DEF_XNAP_XnAP_PDU, NULL, enc_pdu, msgbuf, sizeof(msgbuf)); + AssertFatal(enc.encoded > 0, "aper_encode_to_buffer() failed\n"); + + // 2. Decode + XNAP_XnAP_PDU_t *dec_pdu = NULL; + asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; + asn_dec_rval_t dec = aper_decode(&st, &asn_DEF_XNAP_XnAP_PDU, (void **)&dec_pdu, msgbuf, enc.encoded, 0, 0); + AssertFatal(dec.code == RC_OK, "aper_decode() failed\n"); + + //xer_fprint(stdout, &asn_DEF_XNAP_XnAP_PDU, dec_pdu); + + return dec_pdu; +} + +static void xnap_msg_free(XNAP_XnAP_PDU_t *pdu) +{ + ASN_STRUCT_FREE(asn_DEF_XNAP_XnAP_PDU, pdu); +} + +/** + * 1. Xn Setup Request + */ +static void test_xn_setup_request(void) +{ + /* ---------- Common PLMNs ---------- */ + plmn_id_t plmn0 = { .mcc = 208, .mnc = 95, .mnc_digit_length = 2 }; + plmn_id_t plmn1 = { .mcc = 208, .mnc = 93, .mnc_digit_length = 2 }; + + /* ---------- TAI support (2) ---------- */ + xnap_tai_support_t *tai_support = calloc_or_fail(2, sizeof(*tai_support)); + + /* ================= TAI 0 ================= */ + tai_support[0].tac = 1; + tai_support[0].num_plmn = 2; + tai_support[0].plmn_support = calloc_or_fail(2, sizeof(*tai_support[0].plmn_support)); + + /* ---- TAI 0 / PLMN 0 ---- */ + tai_support[0].plmn_support[0].plmn = plmn0; + tai_support[0].plmn_support[0].num_nssai = 3; + tai_support[0].plmn_support[0].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[0].plmn_support[0].nssai[0] = (nssai_t){ .sst = 1, .sd = 0x010203 }; + tai_support[0].plmn_support[0].nssai[1] = (nssai_t){ .sst = 1, .sd = 0x010204 }; + tai_support[0].plmn_support[0].nssai[2] = (nssai_t){ .sst = 1, .sd = 0x010205 }; + + /* ---- TAI 0 / PLMN 1 ---- */ + tai_support[0].plmn_support[1].plmn = plmn1; + tai_support[0].plmn_support[1].num_nssai = 3; + tai_support[0].plmn_support[1].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[0].plmn_support[1].nssai[0] = (nssai_t){ .sst = 2, .sd = 0x020203 }; + tai_support[0].plmn_support[1].nssai[1] = (nssai_t){ .sst = 2, .sd = 0x020204 }; + tai_support[0].plmn_support[1].nssai[2] = (nssai_t){ .sst = 2, .sd = 0x020205 }; + + /* ================= TAI 1 ================= */ + tai_support[1].tac = 2; + tai_support[1].num_plmn = 2; + tai_support[1].plmn_support = calloc_or_fail(2, sizeof(*tai_support[1].plmn_support)); + + /* ---- TAI 1 / PLMN 0 ---- */ + tai_support[1].plmn_support[0].plmn = plmn0; + tai_support[1].plmn_support[0].num_nssai = 3; + tai_support[1].plmn_support[0].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[1].plmn_support[0].nssai[0] = (nssai_t){ .sst = 3, .sd = 0x030203 }; + tai_support[1].plmn_support[0].nssai[1] = (nssai_t){ .sst = 3, .sd = 0x030204 }; + tai_support[1].plmn_support[0].nssai[2] = (nssai_t){ .sst = 3, .sd = 0x030205 }; + + /* ---- TAI 1 / PLMN 1 ---- */ + tai_support[1].plmn_support[1].plmn = plmn1; + tai_support[1].plmn_support[1].num_nssai = 3; + tai_support[1].plmn_support[1].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[1].plmn_support[1].nssai[0] = (nssai_t){ .sst = 4, .sd = 0x040203 }; + tai_support[1].plmn_support[1].nssai[1] = (nssai_t){ .sst = 4, .sd = 0x040204 }; + tai_support[1].plmn_support[1].nssai[2] = (nssai_t){ .sst = 4, .sd = 0x040205 }; + + /* ---------- AMF region info (2) ---------- */ + xnap_amf_region_info_t *amf_region_info = calloc_or_fail(2, sizeof(*amf_region_info)); + + amf_region_info[0].plmn = plmn0; + amf_region_info[0].amf_region_id = 1; + + amf_region_info[1].plmn = plmn1; + amf_region_info[1].amf_region_id = 2; + + /* ---------- create message ---------- */ + xnap_setup_req_t orig = { + .gNB_id = 0xABCDE, + .plmn = plmn0, + .num_tai = 2, + .tai_support = tai_support, + .num_amf_regions = 2, + .amf_region_info = amf_region_info, + }; + /* ---------- encode ---------- */ + XNAP_XnAP_PDU_t *xnenc = encode_xn_setup_request(&orig); + XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc); + xnap_msg_free(xnenc); + + /* ---------- decode ---------- */ + xnap_setup_req_t decoded = {0}; + bool ret = decode_xn_setup_request(&decoded, xndec); + AssertFatal(ret, "decode_xn_setup_request failed"); + xnap_msg_free(xndec); + + /* ---------- equality ---------- */ + ret = eq_xnap_setup_request(&orig, &decoded); + AssertFatal(ret, "Xn Setup Req mismatch\n"); + free_xnap_setup_request(&decoded); + free_xnap_setup_request(&orig); + printf("%s() successful \n", __func__); +} + +int main() { + printf("Starting XnAP Library Unit Tests...\n"); + + /* Xn Interface Testing */ + test_xn_setup_request(); + + printf("All XnAP tests passed!\n"); + return 0; +} diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index b545d8eb8d..4715bf653b 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -497,6 +497,16 @@ do { \ (bITsTRING)->bits_unused = 4; \ } while(0) +#define MACRO_BIT_STRING_TO_GNB_ID(bITsTRING, oUT) \ +do { \ + uint8_t *_buf = (bITsTRING)->buf; \ + (oUT) = \ + ((uint32_t)_buf[0] << 20) | \ + ((uint32_t)_buf[1] << 12) | \ + ((uint32_t)_buf[2] << 4) | \ + (((uint32_t)_buf[3] & 0xF0) >> 4); \ +} while (0) + /* TS 36.413 v10.9.0 section 9.2.1.38: * E-UTRAN CGI/Cell Identity * The leftmost bits of the Cell From 467015e005c3a469450dbb2bf9e7e5e7b8885535 Mon Sep 17 00:00:00 2001 From: Rakesh BB Date: Sat, 31 Jan 2026 10:16:26 +0000 Subject: [PATCH 17/30] XNAP: add encode/decode and unit test for Xn Setup Response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Xn Setup Response message type definitions - Implement encoder and decoder for Xn Setup Response Xn Setup Response (3GPP TS 38.423v16.2.0 §9.1.3.2) - Global NG-RAN Node ID (M) - TAI Support List (M) - Add equality check and memory management helpers - Extend XNAP library unit tests to cover Setup Response --- openair2/COMMON/xnap_messages_types.h | 10 ++ .../XNAP/lib/xnap_gNB_interface_management.c | 159 ++++++++++++++++++ .../XNAP/lib/xnap_gNB_interface_management.h | 4 + openair2/XNAP/lib/xnap_lib_includes.h | 2 +- openair2/XNAP/tests/xnap_lib_test.c | 85 ++++++++++ 5 files changed, 259 insertions(+), 1 deletion(-) diff --git a/openair2/COMMON/xnap_messages_types.h b/openair2/COMMON/xnap_messages_types.h index 1080e5fb1b..fc360d2558 100644 --- a/openair2/COMMON/xnap_messages_types.h +++ b/openair2/COMMON/xnap_messages_types.h @@ -62,4 +62,14 @@ typedef struct { xnap_amf_region_info_t *amf_region_info; } xnap_setup_req_t; +/* 3GPP TS 38.423 9.1.3.2 – Xn Setup Response */ +typedef struct { + // Global NG-RAN Node ID (gNB_id+plmn) (M) + uint32_t gNB_id; + plmn_id_t plmn; + // TAI Support List (M) + uint16_t num_tai; + xnap_tai_support_t *tai_support; +} xnap_setup_resp_t; + #endif /* XNAP_MESSAGES_TYPES_H_ */ diff --git a/openair2/XNAP/lib/xnap_gNB_interface_management.c b/openair2/XNAP/lib/xnap_gNB_interface_management.c index b374580851..409ce7b967 100644 --- a/openair2/XNAP/lib/xnap_gNB_interface_management.c +++ b/openair2/XNAP/lib/xnap_gNB_interface_management.c @@ -244,3 +244,162 @@ void free_xnap_setup_request(const xnap_setup_req_t *msg) free_xnap_tai_support(msg->tai_support, msg->num_tai); free(msg->amf_region_info); } + +/** + * @brief XnAP Setup Response encoding + */ +XNAP_XnAP_PDU_t *encode_xn_setup_response(const xnap_setup_resp_t *resp) +{ + XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* PDU type */ + pdu->present = XNAP_XnAP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, succMsg); + succMsg->procedureCode = XNAP_ProcedureCode_id_xnSetup; + succMsg->criticality = XNAP_Criticality_reject; + succMsg->value.present = XNAP_SuccessfulOutcome__value_PR_XnSetupResponse; + + XNAP_XnSetupResponse_t *out = &succMsg->value.choice.XnSetupResponse; + + /* Global NG-RAN Node ID (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupResponse_IEs_t, ie1); + ie1->id = XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID; + ie1->criticality = XNAP_Criticality_reject; + ie1->value.present = XNAP_XnSetupResponse_IEs__value_PR_GlobalNG_RANNode_ID; + + XNAP_GlobalNG_RANNode_ID_t *global = &ie1->value.choice.GlobalNG_RANNode_ID; + global->present = XNAP_GlobalNG_RANNode_ID_PR_gNB; + asn1cCalloc(global->choice.gNB, gnb); + + MCC_MNC_TO_PLMNID(resp->plmn.mcc, resp->plmn.mnc, resp->plmn.mnc_digit_length, &gnb->plmn_id); + gnb->gnb_id.present = XNAP_GNB_ID_Choice_PR_gnb_ID; + MACRO_GNB_ID_TO_BIT_STRING(resp->gNB_id, &gnb->gnb_id.choice.gnb_ID); + + /* TAI Support List (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupResponse_IEs_t, ie2); + ie2->id = XNAP_ProtocolIE_ID_id_TAISupport_list; + ie2->criticality = XNAP_Criticality_reject; + ie2->value.present = XNAP_XnSetupResponse_IEs__value_PR_TAISupport_List; + + for (int i = 0; i < resp->num_tai; i++) { + asn1cSequenceAdd(ie2->value.choice.TAISupport_List.list, XNAP_TAISupport_Item_t, taiItem); + INT24_TO_OCTET_STRING(resp->tai_support[i].tac, &taiItem->tac); + + for (int j = 0; j < resp->tai_support[i].num_plmn; j++) { + const xnap_plmn_support_t *plmn = &resp->tai_support[i].plmn_support[j]; + asn1cSequenceAdd(taiItem->broadcastPLMNs.list, XNAP_BroadcastPLMNinTAISupport_Item_t, plmnItem); + MCC_MNC_TO_PLMNID(plmn->plmn.mcc, plmn->plmn.mnc, plmn->plmn.mnc_digit_length, &plmnItem->plmn_id); + + for (int k = 0; k < plmn->num_nssai; k++) { + asn1cSequenceAdd(plmnItem->tAISliceSupport_List.list, XNAP_S_NSSAI_t, nssai); + INT8_TO_OCTET_STRING(plmn->nssai[k].sst, &nssai->sst); + if (plmn->nssai[k].sd) { asn1cCalloc(nssai->sd, sd); INT24_TO_OCTET_STRING(plmn->nssai[k].sd, sd); } + } + } + } + + return pdu; +} + +/** + * @brief XnAP Setup Response decoding + */ +bool decode_xn_setup_response(xnap_setup_resp_t *out, const XNAP_XnAP_PDU_t *pdu) +{ + /* Check presence of message type */ + _EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_successfulOutcome); + AssertError(pdu->choice.successfulOutcome != NULL, return false, "successfulOutcome is NULL"); + _EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, XNAP_ProcedureCode_id_xnSetup); + _EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, XNAP_SuccessfulOutcome__value_PR_XnSetupResponse); + + /* XnSetupResponse container */ + XNAP_XnSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.XnSetupResponse; + XNAP_XnSetupResponse_IEs_t *ie; + + /* Check presence of mandatory IEs */ + XNAP_LIB_FIND_IE(XNAP_XnSetupResponse_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID, true); + XNAP_LIB_FIND_IE(XNAP_XnSetupResponse_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_TAISupport_list, true); + + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + AssertError(in->protocolIEs.list.array[i] != NULL, return false, "protocolIEs.list.array[i] is NULL"); + ie = in->protocolIEs.list.array[i]; + + switch (ie->id) { + + case XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID: { + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupResponse_IEs__value_PR_GlobalNG_RANNode_ID); + XNAP_GlobalNG_RANNode_ID_t *global = &ie->value.choice.GlobalNG_RANNode_ID; + AssertError(global->present == XNAP_GlobalNG_RANNode_ID_PR_gNB, return false, "Only gNB supported"); + AssertError(global->choice.gNB != NULL, return false, "gNB is NULL"); + + PLMNID_TO_MCC_MNC(&global->choice.gNB->plmn_id, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); + AssertError(global->choice.gNB->gnb_id.present == XNAP_GNB_ID_Choice_PR_gnb_ID, return false, "Unsupported gNB ID"); + MACRO_BIT_STRING_TO_GNB_ID(&global->choice.gNB->gnb_id.choice.gnb_ID, out->gNB_id); + } break; + + case XNAP_ProtocolIE_ID_id_TAISupport_list: { + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupResponse_IEs__value_PR_TAISupport_List); + out->num_tai = ie->value.choice.TAISupport_List.list.count; + out->tai_support = calloc_or_fail(out->num_tai, sizeof(*out->tai_support)); + + for (int m = 0; m < out->num_tai; m++) { + XNAP_TAISupport_Item_t *tai = ie->value.choice.TAISupport_List.list.array[m]; + OCTET_STRING_TO_INT24(&tai->tac, out->tai_support[m].tac); + + out->tai_support[m].num_plmn = tai->broadcastPLMNs.list.count; + out->tai_support[m].plmn_support = calloc_or_fail(out->tai_support[m].num_plmn, sizeof(*out->tai_support[m].plmn_support)); + + for (int j = 0; j < out->tai_support[m].num_plmn; j++) { + XNAP_BroadcastPLMNinTAISupport_Item_t *plmn_item = tai->broadcastPLMNs.list.array[j]; + xnap_plmn_support_t *plmn = &out->tai_support[m].plmn_support[j]; + + PLMNID_TO_MCC_MNC(&plmn_item->plmn_id, plmn->plmn.mcc, plmn->plmn.mnc, plmn->plmn.mnc_digit_length); + + plmn->num_nssai = plmn_item->tAISliceSupport_List.list.count; + plmn->nssai = calloc_or_fail(plmn->num_nssai, sizeof(*plmn->nssai)); + + for (int k = 0; k < plmn->num_nssai; k++) { + OCTET_STRING_TO_INT8(&plmn_item->tAISliceSupport_List.list.array[k]->sst, plmn->nssai[k].sst); + if (plmn_item->tAISliceSupport_List.list.array[k]->sd) { + OCTET_STRING_TO_INT24(plmn_item->tAISliceSupport_List.list.array[k]->sd, plmn->nssai[k].sd); + } + } + } + } + } break; + + default: + AssertError(0, return false, "Unknown XnAP IE id %ld\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief XnAP Setup Response main equality check + */ +bool eq_xnap_setup_response(const xnap_setup_resp_t *a, const xnap_setup_resp_t *b) +{ + _EQ_CHECK_UINT32(a->gNB_id, b->gNB_id); + if (!eq_xnap_plmn(&a->plmn, &b->plmn)) return false; + + _EQ_CHECK_INT(a->num_tai, b->num_tai); + for (int i = 0; i < a->num_tai; i++) { + if (!eq_xnap_tai_support(&a->tai_support[i], &b->tai_support[i])) + return false; + } + + return true; +} + +/** + * @brief XnAP Setup Response memory management + */ +void free_xnap_setup_response(const xnap_setup_resp_t *msg) +{ + DevAssert(msg != NULL); + free_xnap_tai_support(msg->tai_support, msg->num_tai); +} + diff --git a/openair2/XNAP/lib/xnap_gNB_interface_management.h b/openair2/XNAP/lib/xnap_gNB_interface_management.h index a4e65d6e00..aab6f777e2 100644 --- a/openair2/XNAP/lib/xnap_gNB_interface_management.h +++ b/openair2/XNAP/lib/xnap_gNB_interface_management.h @@ -27,11 +27,15 @@ typedef struct XNAP_XnAP_PDU XNAP_XnAP_PDU_t; XNAP_XnAP_PDU_t *encode_xn_setup_request(const xnap_setup_req_t *req); +XNAP_XnAP_PDU_t *encode_xn_setup_response(const xnap_setup_resp_t *resp); bool decode_xn_setup_request(xnap_setup_req_t *req, const XNAP_XnAP_PDU_t *pdu); +bool decode_xn_setup_response(xnap_setup_resp_t *out, const XNAP_XnAP_PDU_t *pdu); bool eq_xnap_setup_request(const xnap_setup_req_t *a, const xnap_setup_req_t *b); +bool eq_xnap_setup_response(const xnap_setup_resp_t *a, const xnap_setup_resp_t *b); void free_xnap_setup_request(const xnap_setup_req_t *msg); +void free_xnap_setup_response(const xnap_setup_resp_t *msg); #endif /* XNAP_GNB_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/XNAP/lib/xnap_lib_includes.h b/openair2/XNAP/lib/xnap_lib_includes.h index a67919413a..c45d9cf605 100644 --- a/openair2/XNAP/lib/xnap_lib_includes.h +++ b/openair2/XNAP/lib/xnap_lib_includes.h @@ -29,6 +29,7 @@ #include "XNAP_XnAP-PDU.h" #include "XNAP_ProtocolIE-Field.h" #include "XNAP_InitiatingMessage.h" +#include "XNAP_SuccessfulOutcome.h" #include "XNAP_GlobalgNB-ID.h" #include "XNAP_GlobalNG-RANNode-ID.h" @@ -37,6 +38,5 @@ #include "XNAP_S-NSSAI.h" #include "XNAP_BroadcastPLMNinTAISupport-Item.h" - #endif // XNAP_LIB_INCLUDES_H diff --git a/openair2/XNAP/tests/xnap_lib_test.c b/openair2/XNAP/tests/xnap_lib_test.c index c17f6b4967..610dc7d744 100644 --- a/openair2/XNAP/tests/xnap_lib_test.c +++ b/openair2/XNAP/tests/xnap_lib_test.c @@ -165,11 +165,96 @@ static void test_xn_setup_request(void) printf("%s() successful \n", __func__); } +/** + * 2. Xn Setup Response + */ +static void test_xn_setup_response(void) +{ + /* ---------- Common PLMNs ---------- */ + plmn_id_t plmn0 = { .mcc = 208, .mnc = 95, .mnc_digit_length = 2 }; + plmn_id_t plmn1 = { .mcc = 208, .mnc = 93, .mnc_digit_length = 2 }; + + /* ---------- TAI support (2) ---------- */ + xnap_tai_support_t *tai_support = calloc_or_fail(2, sizeof(*tai_support)); + + /* ================= TAI 0 ================= */ + tai_support[0].tac = 1; + tai_support[0].num_plmn = 2; + tai_support[0].plmn_support = calloc_or_fail(2, sizeof(*tai_support[0].plmn_support)); + + /* ---- TAI 0 / PLMN 0 ---- */ + tai_support[0].plmn_support[0].plmn = plmn0; + tai_support[0].plmn_support[0].num_nssai = 3; + tai_support[0].plmn_support[0].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[0].plmn_support[0].nssai[0] = (nssai_t){ .sst = 1, .sd = 0x010203 }; + tai_support[0].plmn_support[0].nssai[1] = (nssai_t){ .sst = 1, .sd = 0x010204 }; + tai_support[0].plmn_support[0].nssai[2] = (nssai_t){ .sst = 1, .sd = 0x010205 }; + + /* ---- TAI 0 / PLMN 1 ---- */ + tai_support[0].plmn_support[1].plmn = plmn1; + tai_support[0].plmn_support[1].num_nssai = 3; + tai_support[0].plmn_support[1].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[0].plmn_support[1].nssai[0] = (nssai_t){ .sst = 2, .sd = 0x020203 }; + tai_support[0].plmn_support[1].nssai[1] = (nssai_t){ .sst = 2, .sd = 0x020204 }; + tai_support[0].plmn_support[1].nssai[2] = (nssai_t){ .sst = 2, .sd = 0x020205 }; + + /* ================= TAI 1 ================= */ + tai_support[1].tac = 2; + tai_support[1].num_plmn = 2; + tai_support[1].plmn_support = calloc_or_fail(2, sizeof(*tai_support[1].plmn_support)); + + /* ---- TAI 1 / PLMN 0 ---- */ + tai_support[1].plmn_support[0].plmn = plmn0; + tai_support[1].plmn_support[0].num_nssai = 3; + tai_support[1].plmn_support[0].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[1].plmn_support[0].nssai[0] = (nssai_t){ .sst = 3, .sd = 0x030203 }; + tai_support[1].plmn_support[0].nssai[1] = (nssai_t){ .sst = 3, .sd = 0x030204 }; + tai_support[1].plmn_support[0].nssai[2] = (nssai_t){ .sst = 3, .sd = 0x030205 }; + + /* ---- TAI 1 / PLMN 1 ---- */ + tai_support[1].plmn_support[1].plmn = plmn1; + tai_support[1].plmn_support[1].num_nssai = 3; + tai_support[1].plmn_support[1].nssai = calloc_or_fail(3, sizeof(nssai_t)); + + tai_support[1].plmn_support[1].nssai[0] = (nssai_t){ .sst = 4, .sd = 0x040203 }; + tai_support[1].plmn_support[1].nssai[1] = (nssai_t){ .sst = 4, .sd = 0x040204 }; + tai_support[1].plmn_support[1].nssai[2] = (nssai_t){ .sst = 4, .sd = 0x040205 }; + + /* ---------- create message ---------- */ + xnap_setup_resp_t orig = { + .gNB_id = 0xABCDE, + .plmn = plmn0, + .num_tai = 2, + .tai_support = tai_support, + }; + /* ---------- encode ---------- */ + XNAP_XnAP_PDU_t *xnenc = encode_xn_setup_response(&orig); + XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc); + xnap_msg_free(xnenc); + + /* ---------- decode ---------- */ + xnap_setup_resp_t decoded = {0}; + bool ret = decode_xn_setup_response(&decoded, xndec); + AssertFatal(ret, "decode_xn_setup_response failed"); + xnap_msg_free(xndec); + + /* ---------- equality ---------- */ + ret = eq_xnap_setup_response(&orig, &decoded); + AssertFatal(ret, "Xn Setup Response mismatch\n"); + free_xnap_setup_response(&decoded); + free_xnap_setup_response(&orig); + printf("%s() successful \n", __func__); +} + int main() { printf("Starting XnAP Library Unit Tests...\n"); /* Xn Interface Testing */ test_xn_setup_request(); + test_xn_setup_response(); printf("All XnAP tests passed!\n"); return 0; From e34cb240736ed1aedc96e9498ac12d78cf25ad07 Mon Sep 17 00:00:00 2001 From: Rakesh BB Date: Thu, 5 Feb 2026 09:46:19 +0000 Subject: [PATCH 18/30] =?UTF-8?q?XNAP:=20add=20encode/decode=20and=20unit?= =?UTF-8?q?=20test=20for=20Xn=20Setup=20Failure=20=20=20-=20Add=20Xn=20Set?= =?UTF-8?q?up=20Failure=20message=20type=20definitions.=20=20=20-=20Implem?= =?UTF-8?q?ent=20encoder=20and=20decoder=20for=20Xn=20Setup=20Failure.=20?= =?UTF-8?q?=20=20=20=20=20=20Xn=20Setup=20Failure=20(3GPP=20TS=2038.423v16?= =?UTF-8?q?.2.0=20=C2=A79.1.3.3)=20=20=20=20=20=20=20-=20Cause=20(M)=20=20?= =?UTF-8?q?=20-=20Add=20equality=20check=20and=20memory=20management=20hel?= =?UTF-8?q?pers.=20=20=20-=20Extend=20XNAP=20library=20unit=20tests=20to?= =?UTF-8?q?=20cover=20Setup=20Failure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openair2/COMMON/xnap_messages_types.h | 105 ++++++++++++++++++ .../XNAP/lib/xnap_gNB_interface_management.c | 66 +++++++++++ .../XNAP/lib/xnap_gNB_interface_management.h | 4 + openair2/XNAP/lib/xnap_lib_common.c | 66 +++++++++++ openair2/XNAP/lib/xnap_lib_common.h | 4 + openair2/XNAP/lib/xnap_lib_includes.h | 2 + openair2/XNAP/tests/xnap_lib_test.c | 31 ++++++ 7 files changed, 278 insertions(+) diff --git a/openair2/COMMON/xnap_messages_types.h b/openair2/COMMON/xnap_messages_types.h index fc360d2558..bca8bc80f4 100644 --- a/openair2/COMMON/xnap_messages_types.h +++ b/openair2/COMMON/xnap_messages_types.h @@ -72,4 +72,109 @@ typedef struct { xnap_tai_support_t *tai_support; } xnap_setup_resp_t; +typedef enum xnap_cause_radio_network_e { + XNAP_CAUSE_RADIO_NETWORK_LAYER_CELL_NOT_AVAILABLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_HANDOVER_DESIRABLE_FOR_RADIO_REASONS, + XNAP_CAUSE_RADIO_NETWORK_LAYER_HANDOVER_TARGET_NOT_ALLOWED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_INVALID_AMF_SET_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NO_RADIO_RESOURCES_AVAILABLE_IN_TARGET_CELL, + XNAP_CAUSE_RADIO_NETWORK_LAYER_PARTIAL_HANDOVER, + XNAP_CAUSE_RADIO_NETWORK_LAYER_REDUCE_LOAD_IN_SERVING_CELL, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RESOURCE_OPTIMISATION_HANDOVER, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TIME_CRITICAL_HANDOVER, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_RELOCOVERALL_EXPIRY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_RELOCPREP_EXPIRY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_GUAMI_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_LOCAL_NG_RAN_NODE_UE_XNAP_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_INCONSISTENT_REMOTE_NG_RAN_NODE_UE_XNAP_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_ENCRYPTION_AND_OR_INTEGRITY_PROTECTION_ALGORITHMS_NOT_SUPPORTED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_PROTECTION_ALGORITHMS_NOT_SUPPORTED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_MULTIPLE_PDU_SESSION_ID_INSTANCES, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_PDU_SESSION_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_QOS_FLOW_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_MULTIPLE_QOS_FLOW_ID_INSTANCES, + XNAP_CAUSE_RADIO_NETWORK_LAYER_SWITCH_OFF_ONGOING, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NOT_SUPPORTED_5QI_VALUE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_DCOVERALL_EXPIRY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_DCPREP_EXPIRY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_ACTION_DESIRABLE_FOR_RADIO_REASONS, + XNAP_CAUSE_RADIO_NETWORK_LAYER_REDUCE_LOAD, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RESOURCE_OPTIMISATION, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TIME_CRITICAL_ACTION, + XNAP_CAUSE_RADIO_NETWORK_LAYER_TARGET_NOT_ALLOWED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NO_RADIO_RESOURCES_AVAILABLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_INVALID_QOS_COMBINATION, + XNAP_CAUSE_RADIO_NETWORK_LAYER_ENCRYPTION_ALGORITHMS_NOT_SUPPORTED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_PROCEDURE_CANCELLED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RRM_PURPOSE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_IMPROVE_USER_BIT_RATE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_USER_INACTIVITY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RADIO_CONNECTION_WITH_UE_LOST, + XNAP_CAUSE_RADIO_NETWORK_LAYER_FAILURE_IN_THE_RADIO_INTERFACE_PROCEDURE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_BEARER_OPTION_NOT_SUPPORTED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UP_INTEGRITY_PROTECTION_NOT_POSSIBLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UP_CONFIDENTIALITY_PROTECTION_NOT_POSSIBLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE_S, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UE_MAX_IP_DATA_RATE_REASON, + XNAP_CAUSE_RADIO_NETWORK_LAYER_CP_INTEGRITY_PROTECTION_FAILURE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UP_INTEGRITY_PROTECTION_FAILURE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_SLICE_NOT_SUPPORTED_BY_NG_RAN, + XNAP_CAUSE_RADIO_NETWORK_LAYER_MN_MOBILITY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_SN_MOBILITY, + XNAP_CAUSE_RADIO_NETWORK_LAYER_COUNT_REACHES_MAX_VALUE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_OLD_NG_RAN_NODE_UE_XNAP_ID, + XNAP_CAUSE_RADIO_NETWORK_LAYER_PDCP_OVERLOAD, + XNAP_CAUSE_RADIO_NETWORK_LAYER_DRB_ID_NOT_AVAILABLE, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UNSPECIFIED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_UE_CONTEXT_ID_NOT_KNOWN, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NON_RELOCATION_OF_CONTEXT, + XNAP_CAUSE_RADIO_NETWORK_LAYER_CHO_CPC_RESOURCES_TOBECHANGED, + XNAP_CAUSE_RADIO_NETWORK_LAYER_RSN_NOT_AVAILABLE_FOR_THE_UP, + XNAP_CAUSE_RADIO_NETWORK_LAYER_NPN_ACCESS_DENIED +} xnap_cause_radio_network_t; + +typedef enum xnap_cause_transport_layer_e { + XNAP_CAUSE_TRANSPORT_LAYER_TRANSPORT_RESOURCE_UNAVAILABLE, + XNAP_CAUSE_TRANSPORT_LAYER_UNSPECIFIED +} xnap_cause_transport_layer_t; + +typedef enum xnap_cause_protocol_e { + XNAP_CAUSE_PROTOCOL_TRANSFER_SYNTAX_ERROR, + XNAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_REJECT, + XNAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_IGNORE_AND_NOTIFY, + XNAP_CAUSE_PROTOCOL_MESSAGE_NOT_COMPATIBLE_WITH_RECEIVER_STATE, + XNAP_CAUSE_PROTOCOL_SEMANTIC_ERROR, + XNAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_FALSELY_CONSTRUCTED, + XNAP_CAUSE_PROTOCOL_UNSPECIFIED +} xnap_cause_protocol_t; + +typedef enum xnap_cause_misc_e { + XNAP_CAUSE_MISC_CONTROL_PROCESSING_OVERLOAD, + XNAP_CAUSE_MISC_HARDWARE_FAILURE, + XNAP_CAUSE_MISC_O_AND_M_INTERVENTION, + XNAP_CAUSE_MISC_NOT_ENOUGH_USER_PLANE_PROCESSING_RESOURCES, + XNAP_CAUSE_MISC_UNSPECIFIED +} xnap_cause_misc_t; + +typedef enum xnap_cause_group_e { + XNAP_CAUSE_NOTHING, + XNAP_CAUSE_RADIO_NETWORK, + XNAP_CAUSE_TRANSPORT, + XNAP_CAUSE_PROTOCOL, + XNAP_CAUSE_MISC, +} xnap_cause_group_t; + +typedef struct xnap_cause_s { + /* Cause group (e.g. radioNetwork, transport, protocol, misc) */ + xnap_cause_group_t type; + /* Specific cause value within the selected cause group */ + uint8_t value; +} xnap_cause_t; + +/* 3GPP TS 38.423 9.1.3.3 – Xn Setup Failure */ +typedef struct { + // Cause (M) + xnap_cause_t cause; +} xnap_setup_failure_t; + #endif /* XNAP_MESSAGES_TYPES_H_ */ diff --git a/openair2/XNAP/lib/xnap_gNB_interface_management.c b/openair2/XNAP/lib/xnap_gNB_interface_management.c index 409ce7b967..f77543504d 100644 --- a/openair2/XNAP/lib/xnap_gNB_interface_management.c +++ b/openair2/XNAP/lib/xnap_gNB_interface_management.c @@ -403,3 +403,69 @@ void free_xnap_setup_response(const xnap_setup_resp_t *msg) free_xnap_tai_support(msg->tai_support, msg->num_tai); } +/** + * @brief XnAP Setup Failure encoding + */ +XNAP_XnAP_PDU_t *encode_xn_setup_failure(const xnap_setup_failure_t *fail) +{ + XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message type */ + pdu->present = XNAP_XnAP_PDU_PR_unsuccessfulOutcome; + asn1cCalloc(pdu->choice.unsuccessfulOutcome, failMsg); + failMsg->procedureCode = XNAP_ProcedureCode_id_xnSetup; + failMsg->criticality = XNAP_Criticality_reject; + failMsg->value.present = XNAP_UnsuccessfulOutcome__value_PR_XnSetupFailure; + + XNAP_XnSetupFailure_t *out = &failMsg->value.choice.XnSetupFailure; + + /* Cause (M) */ + asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupFailure_IEs_t, ie1); + ie1->id = XNAP_ProtocolIE_ID_id_Cause; + ie1->criticality = XNAP_Criticality_ignore; + ie1->value.present = XNAP_XnSetupFailure_IEs__value_PR_Cause; + xnap_gNB_set_cause(&ie1->value.choice.Cause, &fail->cause); + + return pdu; +} + +/** + * @brief XnAP Setup Failure decoding + */ +bool decode_xn_setup_failure(xnap_setup_failure_t *out, const XNAP_XnAP_PDU_t *pdu) +{ + /* Check message type */ + _EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_unsuccessfulOutcome); + AssertError(pdu->choice.unsuccessfulOutcome != NULL, return false, "unsuccessfulOutcome is NULL"); + _EQ_CHECK_LONG(pdu->choice.unsuccessfulOutcome->procedureCode, XNAP_ProcedureCode_id_xnSetup); + _EQ_CHECK_INT(pdu->choice.unsuccessfulOutcome->value.present, XNAP_UnsuccessfulOutcome__value_PR_XnSetupFailure); + + /* XnSetupFailure container */ + XNAP_XnSetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.XnSetupFailure; + XNAP_XnSetupFailure_IEs_t *ie; + + /* Check presence of mandatory IE */ + XNAP_LIB_FIND_IE(XNAP_XnSetupFailure_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_Cause, true); + + /* Decode Cause */ + _EQ_CHECK_INT(ie->value.present, XNAP_XnSetupFailure_IEs__value_PR_Cause); + out->cause = decode_xnap_cause(&ie->value.choice.Cause); + + return true; +} + +/** + * @brief XnAP Setup Failure equality check + */ +bool eq_xnap_setup_failure(const xnap_setup_failure_t *a, const xnap_setup_failure_t *b) +{ + return eq_xnap_cause(&a->cause, &b->cause); +} + +/** + * @brief XnAP Setup Failure memory management + */ +void free_xnap_setup_failure(xnap_setup_failure_t *msg) +{ + // nothing to free +} diff --git a/openair2/XNAP/lib/xnap_gNB_interface_management.h b/openair2/XNAP/lib/xnap_gNB_interface_management.h index aab6f777e2..f1ffb8811c 100644 --- a/openair2/XNAP/lib/xnap_gNB_interface_management.h +++ b/openair2/XNAP/lib/xnap_gNB_interface_management.h @@ -28,14 +28,18 @@ typedef struct XNAP_XnAP_PDU XNAP_XnAP_PDU_t; XNAP_XnAP_PDU_t *encode_xn_setup_request(const xnap_setup_req_t *req); XNAP_XnAP_PDU_t *encode_xn_setup_response(const xnap_setup_resp_t *resp); +XNAP_XnAP_PDU_t *encode_xn_setup_failure(const xnap_setup_failure_t *fail); bool decode_xn_setup_request(xnap_setup_req_t *req, const XNAP_XnAP_PDU_t *pdu); bool decode_xn_setup_response(xnap_setup_resp_t *out, const XNAP_XnAP_PDU_t *pdu); +bool decode_xn_setup_failure(xnap_setup_failure_t *out, const XNAP_XnAP_PDU_t *pdu); bool eq_xnap_setup_request(const xnap_setup_req_t *a, const xnap_setup_req_t *b); bool eq_xnap_setup_response(const xnap_setup_resp_t *a, const xnap_setup_resp_t *b); +bool eq_xnap_setup_failure(const xnap_setup_failure_t *a, const xnap_setup_failure_t *b); void free_xnap_setup_request(const xnap_setup_req_t *msg); void free_xnap_setup_response(const xnap_setup_resp_t *msg); +void free_xnap_setup_failure(xnap_setup_failure_t *msg); #endif /* XNAP_GNB_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/XNAP/lib/xnap_lib_common.c b/openair2/XNAP/lib/xnap_lib_common.c index 9c6a09c80c..0d9b047ea9 100644 --- a/openair2/XNAP/lib/xnap_lib_common.c +++ b/openair2/XNAP/lib/xnap_lib_common.c @@ -23,6 +23,72 @@ #include "common/utils/assertions.h" #include "common/utils/utils.h" +int xnap_gNB_set_cause(XNAP_Cause_t *cause_p,const xnap_cause_t *in) +{ + DevAssert(cause_p != NULL); + switch (in->type) { + case XNAP_CAUSE_RADIO_NETWORK: + cause_p->present = XNAP_Cause_PR_radioNetwork; + cause_p->choice.radioNetwork = in->value; + break; + case XNAP_CAUSE_TRANSPORT: + cause_p->present = XNAP_Cause_PR_transport; + cause_p->choice.transport = in->value; + break; + case XNAP_CAUSE_PROTOCOL: + cause_p->present = XNAP_Cause_PR_protocol; + cause_p->choice.protocol = in->value; + break; + case XNAP_CAUSE_MISC: + cause_p->present = XNAP_Cause_PR_misc; + cause_p->choice.misc = in->value; + break; + case XNAP_CAUSE_NOTHING: + default: + AssertFatal(false, "unknown cause value %d\n", in->type); + break; + } + return 0; +} + +xnap_cause_t decode_xnap_cause(const XNAP_Cause_t *in) +{ + xnap_cause_t out = {0}; + switch (in->present) { + case XNAP_Cause_PR_radioNetwork: + out.type = XNAP_CAUSE_RADIO_NETWORK; + out.value = in->choice.radioNetwork; + break; + + case XNAP_Cause_PR_transport: + out.type = XNAP_CAUSE_TRANSPORT; + out.value = in->choice.transport; + break; + + case XNAP_Cause_PR_protocol: + out.type = XNAP_CAUSE_PROTOCOL; + out.value = in->choice.protocol; + break; + + case XNAP_Cause_PR_misc: + out.type = XNAP_CAUSE_MISC; + out.value = in->choice.misc; + break; + case XNAP_Cause_PR_NOTHING: + default: + PRINT_ERROR("received illegal XNAP cause %d\n", in->present); + break; + } + return out; +} + +bool eq_xnap_cause(const xnap_cause_t *a, const xnap_cause_t *b) +{ + _EQ_CHECK_INT(a->type, b->type); + _EQ_CHECK_INT(a->value, b->value); + return true; +} + bool eq_xnap_plmn(const plmn_id_t *a, const plmn_id_t *b) { _EQ_CHECK_INT(a->mcc, b->mcc); diff --git a/openair2/XNAP/lib/xnap_lib_common.h b/openair2/XNAP/lib/xnap_lib_common.h index cde0accd88..6186f55471 100644 --- a/openair2/XNAP/lib/xnap_lib_common.h +++ b/openair2/XNAP/lib/xnap_lib_common.h @@ -56,5 +56,9 @@ bool eq_xnap_plmn(const plmn_id_t *a, const plmn_id_t *b); bool eq_xnap_snssai(const nssai_t *a, const nssai_t *b); bool eq_xnap_tai_support(const xnap_tai_support_t *a, const xnap_tai_support_t *b); bool eq_xnap_plmn_support(const xnap_plmn_support_t *a, const xnap_plmn_support_t *b); +bool eq_xnap_cause(const xnap_cause_t *a, const xnap_cause_t *b); + +int xnap_gNB_set_cause(XNAP_Cause_t *cause_p,const xnap_cause_t *in); +xnap_cause_t decode_xnap_cause(const XNAP_Cause_t *in); #endif /* XNAP_LIB_COMMON_H_ */ diff --git a/openair2/XNAP/lib/xnap_lib_includes.h b/openair2/XNAP/lib/xnap_lib_includes.h index c45d9cf605..5e90adbea6 100644 --- a/openair2/XNAP/lib/xnap_lib_includes.h +++ b/openair2/XNAP/lib/xnap_lib_includes.h @@ -30,6 +30,7 @@ #include "XNAP_ProtocolIE-Field.h" #include "XNAP_InitiatingMessage.h" #include "XNAP_SuccessfulOutcome.h" +#include "XNAP_UnsuccessfulOutcome.h" #include "XNAP_GlobalgNB-ID.h" #include "XNAP_GlobalNG-RANNode-ID.h" @@ -37,6 +38,7 @@ #include "XNAP_TAISupport-Item.h" #include "XNAP_S-NSSAI.h" #include "XNAP_BroadcastPLMNinTAISupport-Item.h" +#include "XNAP_Cause.h" #endif // XNAP_LIB_INCLUDES_H diff --git a/openair2/XNAP/tests/xnap_lib_test.c b/openair2/XNAP/tests/xnap_lib_test.c index 610dc7d744..3c1ec3375a 100644 --- a/openair2/XNAP/tests/xnap_lib_test.c +++ b/openair2/XNAP/tests/xnap_lib_test.c @@ -249,12 +249,43 @@ static void test_xn_setup_response(void) printf("%s() successful \n", __func__); } +/** + * 3. Xn Setup Failure + */ +static void test_xn_setup_failure(void) +{ + /* ---------- create message ---------- */ + xnap_setup_failure_t orig = { + .cause.type = XNAP_CAUSE_TRANSPORT, + .cause.value = XNAP_CAUSE_TRANSPORT_LAYER_TRANSPORT_RESOURCE_UNAVAILABLE, + }; + + /* ---------- encode ---------- */ + XNAP_XnAP_PDU_t *xnenc = encode_xn_setup_failure(&orig); + XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc); + xnap_msg_free(xnenc); + + /* ---------- decode ---------- */ + xnap_setup_failure_t decoded = {0}; + bool ret = decode_xn_setup_failure(&decoded, xndec); + AssertFatal(ret, "decode_xn_setup_failure failed"); + xnap_msg_free(xndec); + + /* ---------- equality ---------- */ + ret = eq_xnap_setup_failure(&orig, &decoded); + AssertFatal(ret, "Xn Setup Failure mismatch\n"); + free_xnap_setup_failure(&decoded); + free_xnap_setup_failure(&orig); + printf("%s() successful \n", __func__); +} + int main() { printf("Starting XnAP Library Unit Tests...\n"); /* Xn Interface Testing */ test_xn_setup_request(); test_xn_setup_response(); + test_xn_setup_failure(); printf("All XnAP tests passed!\n"); return 0; From 2e0493632d35d05555ca094f984326ba9100b584 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 28 Jan 2026 09:00:11 +0100 Subject: [PATCH 19/30] RLC data ind: single call for complete TB at gNB --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index ca46f52e9a..ac6a0d6495 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -37,6 +37,7 @@ #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" //#define SRS_IND_DEBUG +#define MAX_NUM_DATA_IND 1024 /* \brief Get the number of UL TDAs that could be used in slot, reachable * via specific k2. The output parameter first_idx is a pointer to the first @@ -395,6 +396,8 @@ static int nr_process_mac_pdu(instance_t module_idP, log_dump(NR_MAC, pduP, pdu_len, LOG_DUMP_CHAR, "\n"); #endif + nr_rlc_data_ind_t data_ind[MAX_NUM_DATA_IND] = {0}; + int num_data_ind = 0; while (pdu_len > 0) { uint16_t mac_len = 0; uint8_t lcid = 0; @@ -416,7 +419,7 @@ static int nr_process_mac_pdu(instance_t module_idP, for (int i = 0; i < print_len; i++) printf("%02x ", pduP[i]); printf("\n"); - return 0; + break; } LOG_D(NR_MAC, @@ -457,7 +460,8 @@ static int nr_process_mac_pdu(instance_t module_idP, if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) { nr_rlc_data_ind_t ind = {.ch = 0, .buf = pduP + mac_subheader_len, .len = mac_len}; - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, &ind, 1); + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); } else { LOG_E(NR_MAC, "prepare_initial_ul_rrc_message() returned false, cannot forward CCCH message\n"); } @@ -477,7 +481,8 @@ static int nr_process_mac_pdu(instance_t module_idP, LOG_I(NR_MAC, "RNTI %04x LCID %d: ignoring %d bytes\n", UE->rnti, lcid, mac_len); } else { nr_rlc_data_ind_t ind = {.ch = lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, &ind, 1); + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); UE->mac_stats.ul.total_sdu_bytes += mac_len; UE->mac_stats.ul.lc_bytes[lcid] += mac_len; @@ -502,7 +507,8 @@ static int nr_process_mac_pdu(instance_t module_idP, UE->mac_stats.ul.lc_bytes[lcid] += mac_len; nr_rlc_data_ind_t ind = {.ch = lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, &ind, 1); + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); sdus += 1; /* Updated estimated buffer when receiving data */ @@ -533,7 +539,7 @@ static int nr_process_mac_pdu(instance_t module_idP, case UL_SCH_LCID_SINGLE_ENTRY_PHR: if (harq_pid < 0) { LOG_E(NR_MAC, "Invalid HARQ PID %d\n", harq_pid); - return 0; + continue; } NR_sched_pusch_t *sched_pusch = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch; @@ -608,14 +614,18 @@ static int nr_process_mac_pdu(instance_t module_idP, case UL_SCH_LCID_PADDING: // End of MAC PDU, can ignore the rest. - return 0; + // 38.321 Sec 6.1.5: "Presence and length of padding is implicit based + // on TB size, size of MAC subPDU(s)." + mac_len = pdu_len - mac_subheader_len; // will make pdu_len go to 0 + break; default: LOG_E(NR_MAC, "RNTI %0x [%d.%d], received unknown MAC header (LCID = 0x%02x)\n", UE->rnti, frameP, slot, lcid); - return -1; + mac_len = pdu_len - mac_subheader_len; // will make pdu_len go to 0 break; } + #ifdef ENABLE_MAC_PAYLOAD_DEBUG if (lcid < 45 || lcid == 52 || lcid == 63) { LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, lcid); @@ -632,6 +642,8 @@ static int nr_process_mac_pdu(instance_t module_idP, pdu_len -= (mac_subheader_len + mac_len); } + nr_mac_rlc_data_ind(module_idP, UE->rnti, true, data_ind, num_data_ind); + UE->mac_stats.ul.num_mac_sdu += sdus; return 0; From c0a78e6c4793cf5168bd2c21fb09f8ea697b49b7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 9 Mar 2026 10:14:46 +0100 Subject: [PATCH 20/30] RLC data ind: single call for complete TB at UE --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 24 ++++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index ffe1c99823..4b548f0d78 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3876,6 +3876,8 @@ static int nr_ue_validate_successrar(uint8_t *pduP, return n; } +#define MAX_NUM_DATA_IND 1024 + /////////////////////////////////// // brief: nr_ue_process_mac_pdu // function: parsing DL PDU header @@ -3941,6 +3943,9 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ pdu_len -= n; } + nr_rlc_data_ind_t data_ind[MAX_NUM_DATA_IND] = {0}; + int num_data_ind = 0; + while (!done && pdu_len > 0){ uint16_t mac_len = 0x0000; uint16_t mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct @@ -3972,7 +3977,8 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ if (mac_len > 0) { LOG_DDUMP(NR_MAC, (void *)pduP, mac_subheader_len + mac_len, LOG_DUMP_CHAR, "DL_SCH_LCID_CCCH (e.g. RRCSetup) payload: "); nr_rlc_data_ind_t ind = {.ch = rx_lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; - nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, &ind, 1); + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); } break; case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH: @@ -4084,8 +4090,11 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ // MAC SDU // From values 1 to 32 it equals to the identity of the logical channel case 1 ... 32: - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return; + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) { + LOG_E(MAC, "get_mac_len(): invalid pdu_len %d (mac_len %d mac_subheader_len %d)\n", pdu_len, mac_len, mac_subheader_len); + done = 1; + break; + } // discard the received subPDU if RB is suspended if (is_lcid_suspended(mac, rx_lcid)) { LOG_W(NR_MAC, "Received PDU for a suspended RB, corresponding to LCID %d. Dropping it.\n", rx_lcid); @@ -4093,7 +4102,8 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ } LOG_D(NR_MAC, "%4d.%2d : DLSCH -> LCID %d %d bytes\n", frameP, slot, rx_lcid, mac_len); nr_rlc_data_ind_t ind = {.ch = rx_lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; - nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, &ind, 1); + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); break; default: LOG_W(MAC, "unknown lcid %02x\n", rx_lcid); @@ -4101,9 +4111,13 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ } pduP += (mac_subheader_len + mac_len); pdu_len -= (mac_subheader_len + mac_len); - if (pdu_len < 0) + if (pdu_len < 0) { LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", mac->ue_id, frameP, slot, pdu_len); + done = 1; + } } + + nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, data_ind, num_data_ind); } /** From 4426fb1a2e53765d855f63df146db0fba6dd721b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 29 Jan 2026 17:26:41 +0100 Subject: [PATCH 21/30] RLC data req: Add API to fill multiple RLC PDUs in one TB, use at gNB Adds the API, which will always prepend a 3 byte header before writing a PDU. This can be used to call less often into RLC, and avoid potential locking. The API is used at the gNB DLSCH scheduler. Also, this removes the "overhead" calculation: since we fill the entire TB at once, RLC will leave space for headers as necessary. --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 50 ++++++------------- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 44 ++++++++++++++++ openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h | 16 ++++++ 3 files changed, 75 insertions(+), 35 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 075e46dd52..313260c225 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -50,6 +50,8 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) +#define MAX_NUM_DATA_REQ 1024 + int get_dl_tda(const gNB_MAC_INST *nrmac, int slot) { /* we assume that this function is mutex-protected from outside */ @@ -1298,47 +1300,25 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) continue; // no data for this LC tbs_size_t len = 0; - int lcid_bytes=0; - while (bufEnd-buf > sizeof(NR_MAC_SUBHEADER_LONG) + 1 ) { - // we do not know how much data we will get from RLC, i.e., whether it - // will be longer than 256B or not. Therefore, reserve space for long header, then - // fetch data, then fill real length + + tb_size_t pdu_siz[MAX_NUM_DATA_REQ]; + int num = nr_mac_rlc_multi_data_req(module_id, rnti, true, lcid, bufEnd - buf, (char *)buf, pdu_siz, sizeofArray(pdu_siz)); + DevAssert(num <= sizeofArray(pdu_siz)); + + sdus += num; + int lcid_bytes = 0; + for (int j = 0; j < num; ++j) { NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; - /* limit requested number of bytes to what preprocessor specified, or - * such that TBS is full */ - const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, - bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); - tbs_size_t len = nr_mac_rlc_data_req(module_id, - rnti, - true, - lcid, - ndata, - (char *)buf+sizeof(NR_MAC_SUBHEADER_LONG)); - LOG_D(NR_MAC, - "%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %ld)\n", - frame, - slot, - rnti, - len, - lcid < 4 ? "DCCH" : "DTCH", - lcid, - ndata, - bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); - - if (len == 0) - break; - - T(T_GNB_MAC_LCID_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(lcid), T_INT(len * 8), T_INT(nr_rlc_tx_list_occupancy(rnti, lcid))); header->R = 0; header->F = 1; header->LCID = lcid; - header->L = htons(len); - buf += len+sizeof(NR_MAC_SUBHEADER_LONG); - dlsch_total_bytes += len; - lcid_bytes += len; - sdus += 1; + header->L = htons(pdu_siz[j]); + buf += pdu_siz[j] + sizeof(NR_MAC_SUBHEADER_LONG); + dlsch_total_bytes += pdu_siz[j]; + lcid_bytes += pdu_siz[j]; } + T(T_GNB_MAC_LCID_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(lcid), T_INT(lcid_bytes), T_INT(nr_rlc_tx_list_occupancy(rnti, lcid))); UE->mac_stats.dl.lc_bytes[lcid] += lcid_bytes; } } else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) { diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 9710df661e..08741b100b 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -191,6 +191,50 @@ void nr_mac_rlc_data_ind(const module_id_t module_idP, nr_rlc_manager_unlock(nr_rlc_ue_manager); } +int nr_mac_rlc_multi_data_req(const module_id_t module_idP, + const uint16_t ue_id, + const bool gnb_flagP, + const logical_chan_id_t channel_idP, + tb_size_t tb_sizeP, + char *buffer_pP, + tb_size_t *pdu_siz, + int pdu_siz_len) +{ + int ret = 0; + + nr_rlc_manager_lock(nr_rlc_ue_manager); + nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); + nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, channel_idP); + + if (rb != NULL) { + rb->set_time(rb, get_nr_rlc_current_time()); + while (tb_sizeP - 3 > 0 && pdu_siz_len > 0) { + // fill PDU in buffer, store size of PDU + pdu_siz[0] = rb->generate_pdu(rb, buffer_pP + 3, tb_sizeP - 3); + if (pdu_siz[0] == 0) + break; + LOG_D(RLC, "MAC PDU created: channel_idP %d len %d\n", channel_idP, pdu_siz[0]); + // reserve header + tb_sizeP -= 3 + pdu_siz[0]; + buffer_pP += 3 + pdu_siz[0]; + pdu_siz++; + pdu_siz_len--; + ret++; + } + } else { + LOG_D(RLC, "MAC PDU failed to get created for channel_idP:%d \n", channel_idP); + ret = 0; + } + + nr_rlc_manager_unlock(nr_rlc_ue_manager); + + if (gnb_flagP) + T(T_ENB_RLC_MAC_DL, T_INT(module_idP), T_INT(ue_id), + T_INT(channel_idP), T_INT(ret)); + + return ret; +} + tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index 93759ef161..cf5d088834 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -51,6 +51,22 @@ void nr_mac_rlc_data_ind(const module_id_t module_idP, const bool gnb_flagP, const nr_rlc_data_ind_t *data, int num_data); +/* \brief Fill up to pdu_siz_len RLC PDUs into buffer pointed to by buffer_pP, + * or until tb_sizeP is reached. Each PDU is preceded by 3 bytes (nothing is + * written) that have to be filled by the consumer (with a MAC sub-PDU + * subheader). This function fills up to an entire TB in a single call, unlike + * nr_mac_rlc_data_req() that fills only one RLC PDU in one step. */ +int nr_mac_rlc_multi_data_req(const module_id_t module_idP, + const uint16_t ue_id, + const bool gnb_flagP, + const logical_chan_id_t channel_idP, + const tb_size_t tb_sizeP, + char *buffer_pP, + tb_size_t *pdu_siz, + int pdu_siz_len); +/* \brief Fill one RLC PDU into buffer pointed to by buffer_pP, or until + * tb_sizeP is reached. Note that NO header is prepended (for a MAC sub-PDU + * subheader), and the user of the API has to fill the necessary data. */ tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, From 4c9b7ec679ad73604814b2294cfe0bf7a6f5b09b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 30 Jan 2026 12:57:26 +0100 Subject: [PATCH 22/30] increase priority of Aerial thread --- nfapi/oai_integration/aerial/fapi_nvIPC.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index bbb0d66900..53717ffdaf 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -355,7 +355,7 @@ void *epoll_recv_task(void *arg) void create_recv_thread(int8_t affinity) { pthread_t thread_id; - threadCreate(&thread_id, epoll_recv_task, NULL, "vnf_nvipc_aerial", affinity, OAI_PRIORITY_RT); + threadCreate(&thread_id, epoll_recv_task, NULL, "vnf_nvipc_aerial", affinity, OAI_PRIORITY_RT_MAX); } int load_hard_code_config(nv_ipc_config_t *config, int module_type, nv_ipc_transport_t _transport) From 17d1e5674ceee26228c94e38892c8500415c2b43 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 30 Jan 2026 16:25:05 +0100 Subject: [PATCH 23/30] reduce max buffer status size --- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 08741b100b..10ff001c49 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -1074,7 +1074,7 @@ bool nr_rlc_get_statistics(int ue_id, int srb_flag, int rb_id, nr_rlc_statistics // Patch buffer status using OAI results (no need to change anything in the RB) // rb->set_time(rb, get_nr_rlc_current_time()); - nr_rlc_entity_buffer_status_t oai_stat = rb->buffer_status(rb, 1000*1000); + nr_rlc_entity_buffer_status_t oai_stat = rb->buffer_status(rb, 256 * 1000); out->rxbuf_occ_bytes = oai_stat.status_size; out->txbuf_occ_bytes = oai_stat.tx_size + oai_stat.retx_size; } else { From 243cd8e9e10611403e5abaee8fa037f8f7d883e9 Mon Sep 17 00:00:00 2001 From: Reem Bahsoun Date: Tue, 3 Mar 2026 08:24:34 +0100 Subject: [PATCH 24/30] Add BladeRF libraries to gNB and UE Docker image builder --- docker/Dockerfile.gNB.ubuntu | 5 +++++ docker/Dockerfile.nrUE.ubuntu | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/docker/Dockerfile.gNB.ubuntu b/docker/Dockerfile.gNB.ubuntu index ded38324d7..bdf5783860 100644 --- a/docker/Dockerfile.gNB.ubuntu +++ b/docker/Dockerfile.gNB.ubuntu @@ -83,6 +83,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_bladerfdevif.so \ /oai-ran/cmake_targets/ran_build/build/libcoding.so \ /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ /oai-ran/cmake_targets/ran_build/build/libdfts.so \ @@ -104,6 +105,9 @@ COPY --from=gnb-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai- ## Copy E2 SM models COPY --from=gnb-build /usr/local/lib/flexric /usr/local/lib/flexric +# Copy BladeRF runtime from base image +COPY --from=gnb-base /usr/local/lib/libbladeRF* /usr/local/lib/ + RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ ldconfig && \ echo "---- ldd on nr-softmodem ----" && \ @@ -112,6 +116,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai ldd /usr/local/lib/liboai_eth_transpro.so \ /usr/local/lib/librfsimulator.so \ /usr/local/lib/liboai_usrpdevif.so \ + /usr/local/lib/liboai_bladerfdevif.so \ /usr/local/lib/libcoding.so \ /usr/local/lib/libparams_libconfig.so \ /usr/local/lib/libdfts.so \ diff --git a/docker/Dockerfile.nrUE.ubuntu b/docker/Dockerfile.nrUE.ubuntu index 08c83899b7..8605ca60a5 100644 --- a/docker/Dockerfile.nrUE.ubuntu +++ b/docker/Dockerfile.nrUE.ubuntu @@ -86,6 +86,7 @@ COPY --from=nr-ue-build \ /oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \ /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ /oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \ + /oai-ran/cmake_targets/ran_build/build/liboai_bladerfdevif.so \ /oai-ran/cmake_targets/ran_build/build/libcoding.so \ /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ /oai-ran/cmake_targets/ran_build/build/libdfts.so \ @@ -102,6 +103,9 @@ COPY --from=nr-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin COPY --from=nr-ue-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib COPY --from=nr-ue-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-nr-ue/bin +# Copy BladeRF runtime from base image +COPY --from=nr-ue-base /usr/local/lib/libbladeRF* /usr/local/lib/ + RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \ ldconfig && \ echo "---- ldd on nr-uesoftmodem ----" && \ @@ -110,6 +114,7 @@ RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai ldd /usr/local/lib/liboai_eth_transpro.so \ /usr/local/lib/librfsimulator.so \ /usr/local/lib/liboai_usrpdevif.so \ + /usr/local/lib/liboai_bladerfdevif.so \ /usr/local/lib/libcoding.so \ /usr/local/lib/libparams_libconfig.so \ /usr/local/lib/libdfts.so \ From e031af0665be9f368401abbe461c39953a8e672b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 11 Mar 2026 15:33:43 +0100 Subject: [PATCH 25/30] USRP: usrp-tx-write-thread: return number of samples written At least writerProcessWaitingQueue() checks for the exact number of samples written. In many other places, we check that the return is non-zero. The usrp-tx-write-thread functionality returned 0, which triggers various problems. Return the number of samples, as in the "direct write" case (if-block before else-block). Co-authored-by: Sagar Arora --- radio/USRP/usrp_lib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp index f224b75354..7cd0f47ee0 100644 --- a/radio/USRP/usrp_lib.cpp +++ b/radio/USRP/usrp_lib.cpp @@ -553,7 +553,7 @@ static int trx_usrp_write(openair0_device_t *device, LOG_D(HW, "Signaling TX TS %llu\n", (unsigned long long)timestamp); pthread_cond_signal(&write_thread->cond_write); pthread_mutex_unlock(&write_thread->mutex_write); - return 0; + return nsamps; } } From 61b3f3b5b4160fa4d7c1646e35895fe7d1ab70d9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 11 Mar 2026 15:45:53 +0100 Subject: [PATCH 26/30] Update RF failed to write warning, add for harmonization The original error was simply "failed to write to RF", which is not very precise. Update with sample numbers for context, and add it in another similar case for consistency. Co-authored-by: Sagar Arora --- radio/COMMON/common_lib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/radio/COMMON/common_lib.c b/radio/COMMON/common_lib.c index 4720347f20..5e12d11e2b 100644 --- a/radio/COMMON/common_lib.c +++ b/radio/COMMON/common_lib.c @@ -217,7 +217,7 @@ static void writerProcessWaitingQueue(nrue_ru_write_t nrue_ru_write, PHY_VARS_NR else wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags); if (wroteSamples != nsamps) - LOG_E(HW, "Failed to write to rf\n"); + LOG_W(HW, "Failed to write to RF: wrote %d out of %d samples\n", wroteSamples, nsamps); } ctx->nextTS = timestamp + nsamps; pthread_mutex_lock(&ctx->mutex_store); @@ -258,6 +258,8 @@ int openair0_write_reorder_common(nrue_ru_write_t nrue_ru_write, wroteSamples = nrue_ru_write(UE, timestamp, txp, nsamps, nbAnt, flags); else wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags); + if (wroteSamples != nsamps) + LOG_W(HW, "Failed to write to RF: wrote %d out of %d samples\n", wroteSamples, nsamps); } else wroteSamples = nsamps; ctx->nextTS = timestamp + nsamps; From d82b5c1ec26775de0599e20f6c4341ae8959f557 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 11 Mar 2026 10:34:11 +0100 Subject: [PATCH 27/30] Bugfix: make longer telnet cmdfunc names The maximum number of cmdfunc names is 20, which IMO is too low. Worse, if it's longer, nothing will warn us because C will just fill the array to it's end (without \0 at the end). To remedy this: - Allow longer names till 64 bytes (I hit the previous limit of 20) - Check that the name is within the length limit: if somebody wants a very long name, the strnlen() will return the maximum length, hitting that assertion. - When reading a command during runtime, allow the corresponding maximum length. On that occasion, also increase total number of permitted cmdfuncs. --- common/utils/telnetsrv/telnetsrv.c | 8 +++++++- common/utils/telnetsrv/telnetsrv.h | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index 407a6b73b9..61bff2310c 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -561,7 +561,7 @@ int process_command(char *buf, int iteration) } rt=CMDSTATUS_NOTFOUND; - j = sscanf(buf,"%19s %19s %m[^\t\n]",modulename,cmd,&cmdb); + j = sscanf(buf,"%19s %63s %m[^\t\n]",modulename,cmd,&cmdb); if (telnetparams.telnetdbg > 0) printf("process_command: %i words, module=%s cmd=%s, parameters= %s\n", j, modulename, cmd, (cmdb == NULL) ? "" : cmdb); @@ -947,6 +947,12 @@ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmdde telnetparams.CmdParsers[i].cmd = cmd; telnetparams.CmdParsers[i].var = var; for (int j = 0; cmd[j].cmdfunc != NULL; j++) { + size_t cmdnamelen = strnlen(cmd[j].cmdname, TELNET_CMD_MAXSIZE); + AssertFatal(cmdnamelen < TELNET_CMD_MAXSIZE, + "cmdname %s too long: %ld >= %d", + cmd[j].cmdname, + cmdnamelen, + TELNET_CMD_MAXSIZE); if (cmd[j].cmdflags & TELNETSRV_CMDFLAG_PUSHINTPOOLQ) { if (afifo == NULL) { afifo = calloc_or_fail(1, sizeof(notifiedFIFO_t)); diff --git a/common/utils/telnetsrv/telnetsrv.h b/common/utils/telnetsrv/telnetsrv.h index b841905cae..bd90513cd1 100644 --- a/common/utils/telnetsrv/telnetsrv.h +++ b/common/utils/telnetsrv/telnetsrv.h @@ -35,8 +35,8 @@ #define TELNET_MAX_MSGLENGTH 2048 #define TELNET_PROMPT_PREFIX "softmodem" -#define TELNET_MAXCMD 20 -#define TELNET_CMD_MAXSIZE 20 +#define TELNET_MAXCMD 64 +#define TELNET_CMD_MAXSIZE 64 #define TELNET_HELPSTR_SIZE 80 /* status return by the command parser after it analysed user input */ From fa72a30bf4ff7ef58307f7b68807f26a8f02c589 Mon Sep 17 00:00:00 2001 From: Merkebu Girmay Date: Fri, 6 Feb 2026 00:37:46 -0800 Subject: [PATCH 28/30] add multi-ue support to vrtsim - Add num_ues and ue_id parameters for server and client configuration - Implement ul combining and dl distribution to all ues - Each ue uses dedicated antenna offsets based on ue_id - Works with no-chanmod mode only and with uniform antenna dimensions across all ues --- radio/vrtsim/vrtsim.c | 411 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 372 insertions(+), 39 deletions(-) diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c index 9a0cd779dc..36780f3ae6 100644 --- a/radio/vrtsim/vrtsim.c +++ b/radio/vrtsim/vrtsim.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "common_lib.h" #include "shm_td_iq_channel.h" #include "SIMULATION/TOOLS/sim.h" @@ -59,6 +60,7 @@ typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; #define MAX_NUM_ANTENNAS_TX 4 #define SAVED_SAMPLES_LEN 256 +#define MAX_NUM_UES MAX_MOBILES_PER_GNB #define ROLE_CLIENT_STRING "client" #define ROLE_SERVER_STRING "server" @@ -90,6 +92,8 @@ typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role; {"cirdb_model_id", "Preferred TDL model id 0..4", 0, .iptr = &vrtsim_state->cirdb_model_id, .defintval = 0, TYPE_INT, 0}, \ {"cirdb_ds_ns", "Desired RMS delay spread in ns", 0, .dblptr = &vrtsim_state->cirdb_ds_ns, .defdblval = 10.0, TYPE_DOUBLE, 0}, \ {"cirdb_speed_mps", "Desired speed in m/s", 0, .dblptr = &vrtsim_state->cirdb_speed_mps, .defdblval = 1.5, TYPE_DOUBLE, 0}, \ + {"num_ues", "Number of UE slots (server only)\n", 0, .iptr = &vrtsim_state->num_ues, .defintval = 1, TYPE_INT, 0}, \ + {"ue_id", "UE slot index 0..num_ues-1 (client only)\n", 0, .iptr = &vrtsim_state->ue_id, .defintval = 0, TYPE_INT, 0}, \ }; // clang-format on @@ -113,6 +117,20 @@ typedef struct tx_timing_s { histogram_t tx_histogram; } tx_timing_t; +typedef struct { + int model_id; + double ds_ns; + double speed_mps; +} cirdb_conf_t; + +typedef struct { + int tx_ant; + int rx_ant; + int tx_offset; + int rx_offset; + cirdb_conf_t cir_conf; +} ue_conf_t; + typedef struct { int role; char *connection_descriptor; @@ -133,6 +151,8 @@ typedef struct { int tx_num_channels; int rx_num_channels; channel_desc_t *channel_desc; + channel_desc_t *channel_desc_per_ue[MAX_NUM_UES]; + pthread_mutex_t cirdb_mutex; Actor_t *channel_modelling_actors; char *taps_socket; int client_num_rx_antennas; @@ -145,6 +165,18 @@ typedef struct { int cirdb_model_id; double cirdb_ds_ns; double cirdb_speed_mps; + // Multi-UE support + int num_ues; + int ue_id; + + ue_conf_t ue_conf[MAX_NUM_UES]; + ue_conf_t ue; + + // Totals + int total_ul_streams; + int total_dl_streams; + sample_t *ul_combine_buffer; + size_t ul_combine_buffer_len; } vrtsim_state_t; static void histogram_add(histogram_t *histogram, double diff) @@ -251,10 +283,11 @@ static void *vrtsim_timing_job(void *arg) } typedef struct client_info_s { - int server_num_rx_antennas; - int client_num_rx_antennas; + int num_ues; + int gnb_num_tx_ant; + int gnb_num_rx_ant; + ue_conf_t ues[MAX_NUM_UES]; } client_info_t; - /** * @brief Publishes the client information information to a file for the client to read. * @@ -293,43 +326,174 @@ static client_info_t client_read_info(char *descriptor_file) return client_info; } +static void parse_ue_config(vrtsim_state_t *vrtsim_state) +{ + AssertFatal(vrtsim_state->num_ues > 0 && vrtsim_state->num_ues <= MAX_NUM_UES, + "num_ues=%d out of range (1..%d)\n", vrtsim_state->num_ues, MAX_NUM_UES); + + for (int i = 0; i < vrtsim_state->num_ues; i++) { + char prefix[64]; + snprintf(prefix, sizeof(prefix), "%s.ue_config.[%d]", VRTSIM_SECTION, i); + + char *antennas = NULL; + int model_id = vrtsim_state->cirdb_model_id; + double ds_ns = vrtsim_state->cirdb_ds_ns; + double speed_mps = vrtsim_state->cirdb_speed_mps; + + paramdef_t ue_params[] = { + {"antennas", "Antenna config e.g. \"1x2\"", 0, .strptr = &antennas, .defstrval = NULL, TYPE_STRING, 0}, + {"model_id", "TDL model id 0..4", 0, .iptr = &model_id, .defintval = vrtsim_state->cirdb_model_id, TYPE_INT, 0}, + {"ds_ns", "Delay spread in ns", 0, .dblptr = &ds_ns, .defdblval = vrtsim_state->cirdb_ds_ns, TYPE_DOUBLE, 0}, + {"speed_mps", "Speed in m/s", 0, .dblptr = &speed_mps, .defdblval = vrtsim_state->cirdb_speed_mps, TYPE_DOUBLE, 0}, + }; + config_get(config_get_if(), ue_params, sizeofArray(ue_params), prefix); + + if (antennas != NULL) { + int tx_ant, rx_ant; + AssertFatal(sscanf(antennas, "%dx%d", &tx_ant, &rx_ant) == 2, + "Invalid antenna format '%s' for UE %d, use e.g. '1x2'\n", antennas, i); + AssertFatal(tx_ant > 0 && tx_ant <= MAX_NUM_ANTENNAS_TX, + "Invalid TX antenna count %d for UE %d\n", tx_ant, i); + AssertFatal(rx_ant > 0 && rx_ant <= MAX_NUM_ANTENNAS_TX, + "Invalid RX antenna count %d for UE %d\n", rx_ant, i); + vrtsim_state->ue_conf[i].tx_ant = tx_ant; + vrtsim_state->ue_conf[i].rx_ant = rx_ant; + } else { + vrtsim_state->ue_conf[i].tx_ant = 1; + vrtsim_state->ue_conf[i].rx_ant = 1; + } + + AssertFatal(model_id >= 0 && model_id <= 4, + "Invalid model_id %d for UE %d (must be 0-4)\n", model_id, i); + AssertFatal(ds_ns > 0, + "Invalid ds_ns %.1f for UE %d (must be > 0)\n", ds_ns, i); + AssertFatal(speed_mps >= 0, + "Invalid speed_mps %.1f for UE %d (must be >= 0)\n", speed_mps, i); + + vrtsim_state->ue_conf[i].cir_conf.model_id = model_id; + vrtsim_state->ue_conf[i].cir_conf.ds_ns = ds_ns; + vrtsim_state->ue_conf[i].cir_conf.speed_mps = speed_mps; + + LOG_I(HW, "VRTSIM: UE %d - %dx%d antennas, Model %d (TDL-%c), DS %.1fns, Speed %.1fm/s\n", + i, + vrtsim_state->ue_conf[i].tx_ant, + vrtsim_state->ue_conf[i].rx_ant, + model_id, 'A' + model_id, ds_ns, speed_mps); + } +} + +static void compute_ue_antenna_offsets(vrtsim_state_t *vrtsim_state) +{ + int tx_offset = 0; + int rx_offset = 0; + + for (int i = 0; i < vrtsim_state->num_ues; i++) { + vrtsim_state->ue_conf[i].tx_offset = tx_offset; + vrtsim_state->ue_conf[i].rx_offset = rx_offset; + + LOG_I(HW, + "VRTSIM: UE %d - TX: %d antennas (offset %d), RX: %d antennas (offset %d)\n", + i, + vrtsim_state->ue_conf[i].tx_ant, + tx_offset, + vrtsim_state->ue_conf[i].rx_ant, + rx_offset); + + tx_offset += vrtsim_state->ue_conf[i].tx_ant; + rx_offset += vrtsim_state->ue_conf[i].rx_ant; + } + + vrtsim_state->total_ul_streams = tx_offset; + vrtsim_state->total_dl_streams = rx_offset; + + LOG_I(HW, "VRTSIM: Total streams - UL: %d, DL: %d\n", vrtsim_state->total_ul_streams, vrtsim_state->total_dl_streams); +} + static int vrtsim_connect(openair0_device_t *device) { vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; // Setup a shared memory channel if (vrtsim_state->role == ROLE_SERVER) { - vrtsim_state->peer_info.num_rx_antennas = vrtsim_state->client_num_rx_antennas; - vrtsim_state->channel = shm_td_iq_channel_create(DEFAULT_CHANNEL_NAME, - vrtsim_state->peer_info.num_rx_antennas, - device->openair0_cfg[0].rx_num_channels); - // Exchange peer info - client_info_t client_info = { - .server_num_rx_antennas = device->openair0_cfg[0].rx_num_channels, - .client_num_rx_antennas = vrtsim_state->client_num_rx_antennas, - }; - server_publish_client_info(client_info, vrtsim_state->connection_descriptor); + parse_ue_config(vrtsim_state); + compute_ue_antenna_offsets(vrtsim_state); + int ul_streams = (vrtsim_state->chanmod || vrtsim_state->taps_socket || vrtsim_state->use_cirdb) + ? vrtsim_state->num_ues * device->openair0_cfg[0].rx_num_channels + : vrtsim_state->total_ul_streams; + vrtsim_state->channel = + shm_td_iq_channel_create(DEFAULT_CHANNEL_NAME, ul_streams, vrtsim_state->total_dl_streams); + size_t max_nsamps = 7680 * 2; + vrtsim_state->ul_combine_buffer = calloc_or_fail(max_nsamps, sizeof(sample_t)); + vrtsim_state->ul_combine_buffer_len = max_nsamps; + // Exchange peer info + + client_info_t client_info = { + .num_ues = vrtsim_state->num_ues, + .gnb_num_tx_ant = device->openair0_cfg[0].tx_num_channels, + .gnb_num_rx_ant = device->openair0_cfg[0].rx_num_channels, + }; + + for (int i = 0; i < vrtsim_state->num_ues; i++) + client_info.ues[i] = vrtsim_state->ue_conf[i]; + + server_publish_client_info(client_info, vrtsim_state->connection_descriptor); + vrtsim_state->peer_info.num_rx_antennas = vrtsim_state->client_num_rx_antennas; + vrtsim_state->last_received_sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel); vrtsim_state->run_timing_thread = true; threadCreate(&vrtsim_state->timing_thread, vrtsim_timing_job, vrtsim_state, "vrtsim_timing", -1, OAI_PRIORITY_RT_MAX); } else { client_info_t client_info = client_read_info(vrtsim_state->connection_descriptor); - AssertFatal(client_info.server_num_rx_antennas > 0, "Server did not publish valid client info, aborting client connection\n"); - AssertFatal( - client_info.client_num_rx_antennas == device->openair0_cfg[0].rx_num_channels, - "Server expects different number of RX antennas. %d != %d. Use server command line option --client-num-rx-antennas\n", - client_info.client_num_rx_antennas, - device->openair0_cfg[0].rx_num_channels); + AssertFatal(client_info.num_ues > 0, "Server did not publish valid num_ues\n"); + AssertFatal(vrtsim_state->ue_id < client_info.num_ues, "ue_id %d >= num_ues %d\n", vrtsim_state->ue_id, client_info.num_ues); + + vrtsim_state->ue = client_info.ues[vrtsim_state->ue_id]; + + AssertFatal(vrtsim_state->ue.tx_ant == device->openair0_cfg[0].tx_num_channels, + "Server expects UE %d to have %d TX antennas, this UE has %d\n", + vrtsim_state->ue_id, + vrtsim_state->ue.tx_ant, + device->openair0_cfg[0].tx_num_channels); + AssertFatal(vrtsim_state->ue.rx_ant == device->openair0_cfg[0].rx_num_channels, + "Server expects UE %d to have %d RX antennas, this UE has %d\n", + vrtsim_state->ue_id, + vrtsim_state->ue.rx_ant, + device->openair0_cfg[0].rx_num_channels); + + LOG_I(HW, + "VRTSIM: UE %d/%d - %dx%d antennas, UL offset=%d, DL offset=%d\n", + vrtsim_state->ue_id, + client_info.num_ues, + vrtsim_state->ue.tx_ant, + vrtsim_state->ue.rx_ant, + vrtsim_state->ue.tx_offset, + vrtsim_state->ue.rx_offset); + if (vrtsim_state->use_cirdb) { + vrtsim_state->cirdb_model_id = vrtsim_state->ue.cir_conf.model_id; + vrtsim_state->cirdb_ds_ns = vrtsim_state->ue.cir_conf.ds_ns; + vrtsim_state->cirdb_speed_mps = vrtsim_state->ue.cir_conf.speed_mps; + + LOG_I(HW, + "VRTSIM: UE %d channel - Model %d (TDL-%c), DS %.1fns, Speed %.1fm/s\n", + vrtsim_state->ue_id, + vrtsim_state->cirdb_model_id, + 'A' + vrtsim_state->cirdb_model_id, + vrtsim_state->cirdb_ds_ns, + vrtsim_state->cirdb_speed_mps); + } vrtsim_state->channel = shm_td_iq_channel_connect(DEFAULT_CHANNEL_NAME, 10); - vrtsim_state->peer_info.num_rx_antennas = client_info.server_num_rx_antennas; + vrtsim_state->peer_info.num_rx_antennas = client_info.gnb_num_rx_ant; vrtsim_state->last_received_sample = shm_td_iq_channel_get_current_sample(vrtsim_state->channel); } // Handle channel modelling after number of RX antennas are known int num_tx_stats = 1; if (vrtsim_state->chanmod || vrtsim_state->taps_socket || vrtsim_state->use_cirdb) { - vrtsim_state->channel_modelling_actors = calloc_or_fail(vrtsim_state->peer_info.num_rx_antennas, sizeof(Actor_t)); - for (int i = 0; i < vrtsim_state->peer_info.num_rx_antennas; i++) { + int num_actors = (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) ? vrtsim_state->total_dl_streams + : vrtsim_state->peer_info.num_rx_antennas; + + vrtsim_state->channel_modelling_actors = calloc_or_fail(num_actors, sizeof(Actor_t)); + for (int i = 0; i < num_actors; i++) { init_actor(&vrtsim_state->channel_modelling_actors[i], "chanmod", -1); } if (vrtsim_state->taps_socket) { @@ -379,16 +543,55 @@ static int vrtsim_connect(openair0_device_t *device) sel.yaml_path ? sel.yaml_path : "(auto)", sel.bin_path ? sel.bin_path : "(auto)"); - cirdb_connect(0, - device->openair0_cfg[0].tx_num_channels, - vrtsim_state->peer_info.num_rx_antennas, - &sel, - &vrtsim_state->channel_desc); - LOG_A(HW, "VRTSIM: channel taps via CIR DB\n"); + // Multi-UE server: create per-UE channel descriptors + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + for (int u = 0; u < vrtsim_state->num_ues; u++) { + cirdb_select_opts_t ue_sel = sel; + ue_sel.want_model_id = vrtsim_state->ue_conf[u].cir_conf.model_id; + ue_sel.want_ds_ns = vrtsim_state->ue_conf[u].cir_conf.ds_ns; + ue_sel.want_speed_mps = vrtsim_state->ue_conf[u].cir_conf.speed_mps; + + AssertFatal(ue_sel.want_model_id >= 0 && ue_sel.want_model_id <= 4, + "Invalid CIRDB model_id=%d for UE %d\n", + ue_sel.want_model_id, + u); + + cirdb_connect(u, + device->openair0_cfg[0].tx_num_channels, + vrtsim_state->ue_conf[u].rx_ant, + &ue_sel, + &vrtsim_state->channel_desc_per_ue[u]); + + channel_desc_t *cd = vrtsim_state->channel_desc_per_ue[u]; + AssertFatal(cd != NULL, "CIRDB failed to create channel_desc for UE %d\n", u); + AssertFatal(cd->nb_tx == device->openair0_cfg[0].tx_num_channels, + "CIRDB shape mismatch UE%d: nb_tx=%d expected %d\n", + u, cd->nb_tx, device->openair0_cfg[0].tx_num_channels); + LOG_I(HW, "VRTSIM: UE %d channel_desc=%p ch_ps=%p ch=%p nb_tx=%d nb_rx=%d\n", + u, cd, cd->ch_ps, cd->ch, cd->nb_tx, cd->nb_rx); + LOG_I(HW, "VRTSIM: UE %d CIRDB - Model %d (TDL-%c), antennas %dx%d, nb_rx=%d\n", + u, ue_sel.want_model_id, 'A' + ue_sel.want_model_id, + device->openair0_cfg[0].tx_num_channels, vrtsim_state->ue_conf[u].rx_ant, cd->nb_rx); + } + vrtsim_state->channel_desc = vrtsim_state->channel_desc_per_ue[0]; + pthread_mutex_init(&vrtsim_state->cirdb_mutex, NULL); + LOG_A(HW, "VRTSIM: Multi-UE channel taps via CIR DB\n"); + } else { + cirdb_connect(0, + device->openair0_cfg[0].tx_num_channels, + vrtsim_state->peer_info.num_rx_antennas, + &sel, + &vrtsim_state->channel_desc); + LOG_A(HW, "VRTSIM: channel taps via CIR DB\n"); + } } else { load_channel_model(vrtsim_state); } num_tx_stats = vrtsim_state->peer_info.num_rx_antennas; + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + vrtsim_state->peer_info.num_rx_antennas = vrtsim_state->total_dl_streams; + num_tx_stats = vrtsim_state->total_dl_streams; + } } vrtsim_state->tx_timing = calloc_or_fail(num_tx_stats, sizeof(tx_timing_t)); for (int i = 0; i < num_tx_stats; i++) { @@ -451,15 +654,69 @@ static void perform_channel_modelling(void *arg) c16_t **input_samples = (c16_t **)channel_modelling_args->samples; channel_desc_t *channel_desc = vrtsim_state->channel_desc; + int local_aarx = aarx; + int global_aarx = aarx; + int target_ue = 0; + + if (vrtsim_state->role == ROLE_CLIENT) { + global_aarx = vrtsim_state->ue_id * vrtsim_state->peer_info.num_rx_antennas + aarx; + } + + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + if (aarx >= vrtsim_state->total_dl_streams) { + LOG_E(HW, "VRTSIM: aarx=%d >= total_dl_streams=%d\n", aarx, vrtsim_state->total_dl_streams); + return; + } + + bool found = false; + for (int u = 0; u < vrtsim_state->num_ues; u++) { + int offset = vrtsim_state->ue_conf[u].rx_offset; + int count = vrtsim_state->ue_conf[u].rx_ant; + if (aarx >= offset && aarx < offset + count) { + target_ue = u; + local_aarx = aarx - offset; + channel_desc = vrtsim_state->channel_desc_per_ue[u]; + found = true; + break; + } + } + + if (!found) { + LOG_E(HW, "VRTSIM: aarx=%d could not map to any UE (total_dl_streams=%d)\n", aarx, vrtsim_state->total_dl_streams); + return; + } + } if (channel_desc == NULL) { + LOG_E(HW, "VRTSIM: channel_desc is NULL for aarx=%d\n", aarx); + return; + } + + // Bounds check: ensure local_aarx is within channel_desc bounds + if (local_aarx >= channel_desc->nb_rx) { + LOG_E(HW, + "VRTSIM: UE%d local_aarx=%d >= nb_rx=%d (global aarx=%d). CIRDB shape mismatch.\n", + target_ue, + local_aarx, + channel_desc->nb_rx, + aarx); return; } if (vrtsim_state->use_cirdb) { double seconds = (double)channel_modelling_args->timestamp / vrtsim_state->sample_rate; uint64_t elapsed_ns = (uint64_t)(seconds * 1e9 + 0.5); + + // Lock for multi-UE to prevent concurrent CIRDB updates + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + pthread_mutex_lock(&vrtsim_state->cirdb_mutex); + } + cirdb_update(elapsed_ns); + + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + pthread_mutex_unlock(&vrtsim_state->cirdb_mutex); + } } cf_t channel_impulse_response[nb_tx_ant][channel_desc->channel_length]; @@ -468,7 +725,7 @@ static void perform_channel_modelling(void *arg) const float pathloss_linear = powf(10, channel_desc->path_loss_dB / 20.0); // Convert channel impulse response to float + apply pathloss for (int aatx = 0; aatx < nb_tx_ant; aatx++) { - const struct complexd *channelModel = channel_desc->ch[aarx + (aatx * channel_desc->nb_rx)]; + const struct complexd *channelModel = channel_desc->ch[local_aarx + (aatx * channel_desc->nb_rx)]; for (int i = 0; i < channel_desc->channel_length; i++) { channel_impulse_response[aatx][i].r = channelModel[i].r * pathloss_linear; channel_impulse_response[aatx][i].i = channelModel[i].i * pathloss_linear; @@ -477,7 +734,7 @@ static void perform_channel_modelling(void *arg) } } else { for (int aatx = 0; aatx < nb_tx_ant; aatx++) { - struct complexf *channelModel = channel_desc->ch_ps[aarx + (aatx * channel_desc->nb_rx)]; + struct complexf *channelModel = channel_desc->ch_ps[local_aarx + (aatx * channel_desc->nb_rx)]; channel_impulse_response_p[aatx] = channelModel; } } @@ -537,7 +794,7 @@ static void perform_channel_modelling(void *arg) channel_modelling_args->timestamp + start_sample, samples_out, num_samples, - aarx, + global_aarx, channel_modelling_args->flags, aarx); } @@ -623,8 +880,27 @@ static int vrtsim_write(openair0_device_t *device, timestamp -= device->openair0_cfg->command_line_sample_advance; vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv; bool channel_modelling = vrtsim_state->chanmod || vrtsim_state->taps_socket || vrtsim_state->use_cirdb; - return channel_modelling ? vrtsim_write_with_chanmod(vrtsim_state, timestamp, samplesVoid, nsamps, nbAnt, flags) - : vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[0], nsamps, 0, flags, 0); + if (channel_modelling) { + return vrtsim_write_with_chanmod(vrtsim_state, timestamp, samplesVoid, nsamps, nbAnt, flags); + } + if (vrtsim_state->role == ROLE_CLIENT) { + for (int aatx = 0; aatx < nbAnt; aatx++) { + int global_ul_ant = vrtsim_state->ue.tx_offset + aatx; + vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[aatx], nsamps, global_ul_ant, flags, 0); + } + return nsamps; + } else { + AssertFatal(nbAnt == 1, "Multi-TX gNB not yet supported in multi-UE no-chanmod mode\n"); + for (int u = 0; u < vrtsim_state->num_ues; u++) { + int rx_offset = vrtsim_state->ue_conf[u].rx_offset; + int num_rx_ant = vrtsim_state->ue_conf[u].rx_ant; + for (int aarx = 0; aarx < num_rx_ant; aarx++) { + int global_dl_ant = rx_offset + aarx; + vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[0], nsamps, global_dl_ant, flags, 0); + } + } + return nsamps; + } } static int vrtsim_write_beams(openair0_device_t *device, @@ -665,12 +941,62 @@ static int vrtsim_read(openair0_device_t *device, openair0_timestamp_t *ptimesta } } } - - int ret = shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, 0, samplesVoid[0]); - if (ret == CHANNEL_ERROR_TOO_LATE) { - vrtsim_state->rx_samples_late += nsamps; - } else if (ret == CHANNEL_ERROR_TOO_EARLY) { - vrtsim_state->rx_early += 1; + if (vrtsim_state->role == ROLE_SERVER) { + if (vrtsim_state->num_ues > 1) { + /* Multi-UE UL combining */ + if (nsamps > vrtsim_state->ul_combine_buffer_len) { + sample_t *tmp = realloc(vrtsim_state->ul_combine_buffer, nsamps * sizeof(sample_t)); + AssertFatal(tmp != NULL, "Failed to realloc UL combine buffer\n"); + vrtsim_state->ul_combine_buffer = tmp; + vrtsim_state->ul_combine_buffer_len = nsamps; + } + for (int aarx = 0; aarx < nbAnt; aarx++) + memset(samplesVoid[aarx], 0, nsamps * sizeof(sample_t)); + for (int u = 0; u < vrtsim_state->num_ues; u++) { + for (int aarx = 0; aarx < nbAnt; aarx++) { + int stream = u * nbAnt + aarx; + int ret = shm_td_iq_channel_rx(vrtsim_state->channel, + vrtsim_state->last_received_sample, + nsamps, + stream, + vrtsim_state->ul_combine_buffer); + if (ret == CHANNEL_ERROR_TOO_LATE) { + vrtsim_state->rx_samples_late += nsamps; + } else if (ret == CHANNEL_ERROR_TOO_EARLY) { + vrtsim_state->rx_early += 1; + } + int16_t *out = (int16_t *)samplesVoid[aarx]; + int16_t *in = (int16_t *)vrtsim_state->ul_combine_buffer; + for (int i = 0; i < nsamps * 2; i++) { + int32_t sum = (int32_t)out[i] + (int32_t)in[i]; + out[i] = (int16_t)((sum > 32767) ? 32767 : (sum < -32768) ? -32768 : sum); + } + } + } + } else { + /* Single-UE server UL read */ + int ret = shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, 0, samplesVoid[0]); + if (ret == CHANNEL_ERROR_TOO_LATE) { + vrtsim_state->rx_samples_late += nsamps; + } else if (ret == CHANNEL_ERROR_TOO_EARLY) { + vrtsim_state->rx_early += 1; + } + for (int aarx = 1; aarx < nbAnt; aarx++) { + if (samplesVoid[aarx] != NULL) + memcpy(samplesVoid[aarx], samplesVoid[0], nsamps * sizeof(sample_t)); + } + } + } else { + for (int aarx = 0; aarx < nbAnt; aarx++) { + int global_dl_ant = vrtsim_state->ue.rx_offset + aarx; + int ret = + shm_td_iq_channel_rx(vrtsim_state->channel, vrtsim_state->last_received_sample, nsamps, global_dl_ant, samplesVoid[aarx]); + if (ret == CHANNEL_ERROR_TOO_LATE) { + vrtsim_state->rx_samples_late += nsamps; + } else if (ret == CHANNEL_ERROR_TOO_EARLY) { + vrtsim_state->rx_early += 1; + } + } } vrtsim_state->rx_samples_total += nsamps; *ptimestamp = vrtsim_state->last_received_sample; @@ -693,6 +1019,9 @@ static void vrtsim_end(openair0_device_t *device) shutdown_actor(&vrtsim_state->channel_modelling_actors[i]); } free(vrtsim_state->channel_modelling_actors); + if (vrtsim_state->use_cirdb && vrtsim_state->role == ROLE_SERVER && vrtsim_state->num_ues > 1) { + pthread_mutex_destroy(&vrtsim_state->cirdb_mutex); + } for (int i = 1; i < vrtsim_state->peer_info.num_rx_antennas; i++) { histogram_merge(&tx_timing->tx_histogram, &tx_timing[i].tx_histogram); tx_timing->tx_early += tx_timing[i].tx_early; @@ -708,6 +1037,10 @@ static void vrtsim_end(openair0_device_t *device) taps_client_stop(); } } + if (vrtsim_state->role == ROLE_SERVER && vrtsim_state->ul_combine_buffer) { + free(vrtsim_state->ul_combine_buffer); + vrtsim_state->ul_combine_buffer = NULL; + } shm_td_iq_channel_abort(vrtsim_state->channel); sleep(1); shm_td_iq_channel_destroy(vrtsim_state->channel); From 694f7bea084393f52255a95a2a9870375b901f96 Mon Sep 17 00:00:00 2001 From: Merkebu Girmay Date: Fri, 27 Feb 2026 22:10:08 -0800 Subject: [PATCH 29/30] Add CI test for multi-UE vrtsim with CIRDB --- .../container_5g_vrtsim_multiue_gh.xml | 183 +++++++++++++++ .../5g_vrtsim_multiue/docker-compose.yaml | 212 ++++++++++++++++++ 2 files changed, 395 insertions(+) create mode 100644 ci-scripts/xml_files/container_5g_vrtsim_multiue_gh.xml create mode 100644 ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml diff --git a/ci-scripts/xml_files/container_5g_vrtsim_multiue_gh.xml b/ci-scripts/xml_files/container_5g_vrtsim_multiue_gh.xml new file mode 100644 index 0000000000..c2da848374 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_vrtsim_multiue_gh.xml @@ -0,0 +1,183 @@ + + + vrtsim-5gnr-multiue-gh + Multi-UE gNB vrtsim + CIRDB + wrench + + + Pull_Local_Registry + Pull Images from Local Registry + localhost + oai-gnb oai-nr-ue + arm_ + + + + Create_Workspace + Create new Workspace + localhost + + + + Deploy_Object + Deploy OAI 5G CoreNetwork + localhost + ci-scripts/yaml_files/5g_vrtsim_multiue + mysql oai-amf oai-smf oai-upf oai-ext-dn + + + + Deploy_Object + Deploy OAI 5G gNB+UE RF sim SA + localhost + ci-scripts/yaml_files/5g_vrtsim_multiue + oai-gnb oai-nr-ue0 oai-nr-ue1 + + + + Attach_UE + Attach OAI UE 1 (Wait for IP) + rfsim5g_ue + localhost + + + + Attach_UE + Attach OAI UE 2 (Wait for IP) + rfsim5g_ue2 + localhost + + + + Ping + Ping ext-dn from NR-UE + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + -c 20 -i 0.25 + 5 + + + + Ping + Ping NR-UE from ext-dn + rfsim5g_ext_dn + localhost + rfsim5g_ue + localhost + -c 20 -i 0.25 + 5 + + + + Iperf + Iperf UE 1 (DL/3Mbps/UDP)(30 sec) + -u -b 3M -t 30 -R + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Iperf + Iperf UE 1 (UL/1Mbps/UDP)(30 sec) + -u -b 1M -t 30 + rfsim5g_ue + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Ping + Ping ext-dn from UE 2 + rfsim5g_ue2 + localhost + rfsim5g_ext_dn + localhost + -c 20 -i 0.25 + 5 + + + + Ping + Ping UE 2 from ext-dn + rfsim5g_ext_dn + localhost + rfsim5g_ue2 + localhost + -c 20 -i 0.25 + 5 + + + + Iperf + Iperf UE 2 (DL/3Mbps/UDP)(30 sec) + -u -b 3M -t 30 -R + rfsim5g_ue2 + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Iperf + Iperf UE 2 (UL/1Mbps/UDP)(30 sec) + -u -b 1M -t 30 + rfsim5g_ue2 + localhost + rfsim5g_ext_dn + localhost + 5 + 90 + + + + Undeploy_Object + true + Undeploy all OAI 5G stack + localhost + ci-scripts/yaml_files/5g_vrtsim_multiue + + oai-gnb=EndsWithBye oai-nr-ue0 oai-nr-ue1 + + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + localhost + oai-gnb oai-nr-ue + + + diff --git a/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml b/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml new file mode 100644 index 0000000000..c87be3a998 --- /dev/null +++ b/ci-scripts/yaml_files/5g_vrtsim_multiue/docker-compose.yaml @@ -0,0 +1,212 @@ +services: + # CIR Generator service - generates CIRDB files on every CI run + cir-generator: + image: oaisoftwarealliance/cir-generator:test + environment: + GENERATOR_ARGS: "--demo" + OUTPUT: "--out /opt/output/cir_db.bin" + volumes: + - cirdb_data:/opt/output + + mysql: + container_name: "rfsim5g-mysql" + image: mysql:8.0 + init: true + volumes: + - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + start_period: 10s + start_interval: 500ms + retries: 30 + networks: + public_net: + ipv4_address: 192.168.71.131 + + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oaisoftwarealliance/oai-amf:v2.1.10 + environment: + - TZ=Europe/paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml + depends_on: + - mysql + networks: + public_net: + ipv4_address: 192.168.71.132 + + oai-smf: + container_name: "rfsim5g-oai-smf" + image: oaisoftwarealliance/oai-smf:v2.1.10 + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml + depends_on: + - oai-amf + networks: + public_net: + ipv4_address: 192.168.71.133 + + oai-upf: + container_name: "rfsim5g-oai-upf" + image: oaisoftwarealliance/oai-upf:v2.1.10 + init: true + environment: + - TZ=Europe/Paris + volumes: + - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml + depends_on: + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + networks: + public_net: + ipv4_address: 192.168.71.134 + interface_name: eth0 + traffic_net: + ipv4_address: 192.168.72.134 + interface_name: eth1 + + oai-ext-dn: + privileged: true + container_name: rfsim5g-oai-ext-dn + image: oaisoftwarealliance/trf-gen-cn5g:latest + init: true + entrypoint: /bin/bash -c \ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity" + depends_on: + - oai-upf + networks: + traffic_net: + ipv4_address: 192.168.72.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.72.134" + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + start_interval: 500ms + + oai-gnb: + image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop} + container_name: rfsim5g-oai-gnb + cap_drop: + - ALL + environment: + USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.num_ues 2 --vrtsim.cirdb 1 --vrtsim.cirdb_file /cirdb/cir_db.bin --vrtsim.cirdb_yaml /cirdb/cir_db.yaml --vrtsim.ue_config.[0].antennas 1x2 --vrtsim.ue_config.[0].model_id 0 --vrtsim.ue_config.[0].ds_ns 10.0 --vrtsim.ue_config.[0].speed_mps 1.5 --vrtsim.ue_config.[1].antennas 2x2 --vrtsim.ue_config.[1].model_id 1 --vrtsim.ue_config.[1].ds_ns 10.0 --vrtsim.ue_config.[1].speed_mps 1.5 --gNBs.[0].min_rxtxtime 8 + depends_on: + cir-generator: + condition: service_completed_successfully + oai-ext-dn: + condition: service_started + networks: + public_net: + ipv4_address: 192.168.71.140 + volumes: + - ../../conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml:/opt/oai-gnb/etc/gnb.yaml + - cirdb_data:/cirdb:ro + - tmp_data:/tmp/ + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + start_period: 10s + start_interval: 500ms + retries: 5 + ipc: host + + oai-nr-ue0: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue + cap_drop: + - ALL + cap_add: + - NET_ADMIN + - NET_RAW + environment: + USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 0 --ue-nb-ant-tx 1 --ue-nb-ant-rx 2 + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.150 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.vrtsim.chanmod.yaml:/opt/oai-nr-ue/etc/nr-ue.yaml + - tmp_data:/tmp/ + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + start_interval: 500ms + ipc: host + + oai-nr-ue1: + image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop} + container_name: rfsim5g-oai-nr-ue2 + cap_drop: + - ALL + cap_add: + - NET_ADMIN + - NET_RAW + environment: + USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3319680000 --ssb 516 --uicc0.imsi 208990100001101 --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role client --vrtsim.ue_id 1 --ue-nb-ant-tx 2 --ue-nb-ant-rx 2 + depends_on: + - oai-gnb + networks: + public_net: + ipv4_address: 192.168.71.151 + devices: + - /dev/net/tun:/dev/net/tun + volumes: + - ../../conf_files/nrue.vrtsim.chanmod.yaml:/opt/oai-nr-ue/etc/nr-ue.yaml + - tmp_data:/tmp/ + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + start_interval: 500ms + ipc: host + +networks: + public_net: + driver: bridge + name: rfsim5g-oai-public-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-public" + traffic_net: + driver: bridge + name: rfsim5g-oai-traffic-net + ipam: + config: + - subnet: 192.168.72.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-traffic" + +volumes: + tmp_data: + cirdb_data: From 96511595f2a86e768c81fcc08b0424a9b318383d Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Thu, 12 Mar 2026 22:17:05 +0100 Subject: [PATCH 30/30] Reduce timing reference value for feptx_total in 40 MHz phytest The reduction reflects improved feptx_total performance introduced in !3834. --- ci-scripts/datalog_rt_stats.default.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 65fd678b0f..3335658795 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -20,7 +20,7 @@ Ref : Slot Indication : 5.0 feprx : 43.0 feptx_ofdm (per port, half_slot) : 30 - feptx_total : 57 + feptx_total : 43 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25