From 5ac703b58039661a62af076590f5394fb7d02edf Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 28 Nov 2024 15:01:14 -0500 Subject: [PATCH 1/4] Code cleanup Add const to function input pointer. --- executables/nr-ue.c | 7 ++++--- openair1/SCHED_NR_UE/phy_frame_config_nr.h | 2 +- openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c | 12 ++++++------ openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index e2882b4224..e883170438 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -443,6 +443,7 @@ static void UE_synch(void *arg) { static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action) { PHY_VARS_NR_UE *UE = rxtxD->UE; + const fapi_nr_config_request_t *cfg = &UE->nrUE_config; const UE_nr_rxtx_proc_t *proc = &rxtxD->proc; NR_DL_FRAME_PARMS *fp = &UE->frame_parms; @@ -466,10 +467,10 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action) flags = TX_BURST_START_AND_END; } else { int slots_frame = fp->slots_per_frame; - int curr_slot = nr_ue_slot_select(&UE->nrUE_config, slot); + int curr_slot = nr_ue_slot_select(cfg, slot); if (curr_slot != NR_DOWNLINK_SLOT) { - int next_slot = nr_ue_slot_select(&UE->nrUE_config, (slot + 1) % slots_frame); - int prev_slot = nr_ue_slot_select(&UE->nrUE_config, (slot + slots_frame - 1) % slots_frame); + int next_slot = nr_ue_slot_select(cfg, (slot + 1) % slots_frame); + int prev_slot = nr_ue_slot_select(cfg, (slot + slots_frame - 1) % slots_frame); if (prev_slot == NR_DOWNLINK_SLOT) flags = TX_BURST_START; else if (next_slot == NR_DOWNLINK_SLOT) diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr.h b/openair1/SCHED_NR_UE/phy_frame_config_nr.h index 59df0ba959..359722a7be 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr.h +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr.h @@ -72,7 +72,7 @@ int slot_select_nr(NR_DL_FRAME_PARMS *frame_parms, int nr_frame, int nr_slot); * @param nr_slot : slot number @returns int : downlink, uplink or mixed slot type */ -int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_slot); +int nr_ue_slot_select(const fapi_nr_config_request_t *cfg, int nr_slot); /** \brief This function frees tdd configuration for nr * @param frame_parms NR DL Frame parameters diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c index f2541d21b3..4fbe241223 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr_ue.c @@ -39,7 +39,7 @@ * *********************************************************************/ -int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_slot) +int nr_ue_slot_select(const fapi_nr_config_request_t *cfg, int nr_slot) { if (cfg->cell_config.frame_duplex_type == FDD) return NR_UPLINK_SLOT | NR_DOWNLINK_SLOT; @@ -47,7 +47,7 @@ int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_slot) int period = cfg->tdd_table_1.tdd_period_in_slots + (cfg->tdd_table_2 ? cfg->tdd_table_2->tdd_period_in_slots : 0); int rel_slot = nr_slot % period; - fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table_1; + const fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table_1; if (cfg->tdd_table_2 && rel_slot >= tdd_table->tdd_period_in_slots) { rel_slot -= tdd_table->tdd_period_in_slots; tdd_table = cfg->tdd_table_2; @@ -56,7 +56,7 @@ int nr_ue_slot_select(fapi_nr_config_request_t *cfg, int nr_slot) if (tdd_table->max_tdd_periodicity_list == NULL) // this happens before receiving TDD configuration return NR_DOWNLINK_SLOT; - fapi_nr_max_tdd_periodicity_t *current_slot = &tdd_table->max_tdd_periodicity_list[rel_slot]; + const fapi_nr_max_tdd_periodicity_t *current_slot = &tdd_table->max_tdd_periodicity_list[rel_slot]; // if the 1st symbol is UL the whole slot is UL if (current_slot->max_num_of_symbol_per_slot_list[0].slot_config == 1) @@ -109,7 +109,7 @@ uint8_t sl_determine_if_sidelink_slot(uint8_t sl_startsym, uint8_t sl_lensym, ui * Mixed Slot is a sidelink slot if the uplink symbols in Mixed slot * overlaps with Sidelink start symbol and number of symbols. */ -int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg, int slot, uint8_t frame_duplex_type) +int sl_nr_ue_slot_select(const sl_nr_phy_config_request_t *cfg, int slot, uint8_t frame_duplex_type) { int ul_sym = 0, slot_type = 0; @@ -122,9 +122,9 @@ int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg, int slot, uint8_t fram int period = cfg->tdd_table.tdd_period_in_slots; int rel_slot = slot % period; - fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table; + const fapi_nr_tdd_table_t *tdd_table = &cfg->tdd_table; - fapi_nr_max_tdd_periodicity_t *current_slot = &tdd_table->max_tdd_periodicity_list[rel_slot]; + 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++) { if (current_slot->max_num_of_symbol_per_slot_list[symbol_count].slot_config == 1) { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 094d1e5965..2f3acadeca 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -447,7 +447,7 @@ uint8_t sl_determine_sci_1a_len(uint16_t *num_subchannels, * @param nr_slot : slot number * @param frame duplex type : Frame type @returns int : 0 or Sidelink slot type */ -int sl_nr_ue_slot_select(sl_nr_phy_config_request_t *cfg, int nr_slot, uint8_t frame_duplex_type); +int sl_nr_ue_slot_select(const sl_nr_phy_config_request_t *cfg, int nr_slot, uint8_t frame_duplex_type); void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac); From 4f56bf903a29f90a5c822e5964ea9a14e9ee93b8 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sat, 30 Nov 2024 16:56:48 -0500 Subject: [PATCH 2/4] Helper function to get center frequency from point A. --- executables/nr-ue.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index e883170438..cbeecb990a 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -558,6 +558,13 @@ void processSlotTX(void *arg) TracyCZoneEnd(ctx); } +static uint64_t get_carrier_frequency(const int N_RB, const int mu, const uint32_t pointA_freq_khz) +{ + const uint64_t bw = (NR_NB_SC_PER_RB * N_RB) * MU_SCS(mu); + const uint64_t carrier_freq = (pointA_freq_khz + bw / 2) * 1000; + return carrier_freq; +} + static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc, int *tx_wait_for_dlsch, @@ -584,10 +591,9 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell; UE->target_Nid_cell = synch_req->target_Nid_cell; - uint64_t dl_bw = (12 * fp->N_RB_DL) * (15000 << fp->numerology_index); - uint64_t dl_CarrierFreq = (dl_bw >> 1) + (uint64_t)UE->nrUE_config.carrier_config.dl_frequency * 1000; - uint64_t ul_bw = (12 * fp->N_RB_UL) * (15000 << fp->numerology_index); - uint64_t ul_CarrierFreq = (ul_bw >> 1) + (uint64_t)UE->nrUE_config.carrier_config.uplink_frequency * 1000; + const fapi_nr_ue_carrier_config_t *cfg = &UE->nrUE_config.carrier_config; + uint64_t dl_CarrierFreq = get_carrier_frequency(fp->N_RB_DL, fp->numerology_index, cfg->dl_frequency); + uint64_t ul_CarrierFreq = get_carrier_frequency(fp->N_RB_UL, fp->numerology_index, cfg->uplink_frequency); if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) { fp->dl_CarrierFreq = dl_CarrierFreq; fp->ul_CarrierFreq = ul_CarrierFreq; From e5814cd62e66ade8bedea3686d94b7677862f758 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Sat, 30 Nov 2024 17:12:38 -0500 Subject: [PATCH 3/4] Handle sync request out of UE_dl_preprocessing() Move handling of sync request from MAC from UE_dl_preprocessing(). This will process the sync request before receiving the samples of current slot from radio so we don't 'lose' the slot. --- executables/nr-ue.c | 64 +++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index cbeecb990a..1dd1836fa7 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -565,6 +565,38 @@ static uint64_t get_carrier_frequency(const int N_RB, const int mu, const uint32 return carrier_freq; } +static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE) +{ + NR_DL_FRAME_PARMS *fp = &UE->frame_parms; + // Start synchronization with a target gNB + if (UE->synch_request.received_synch_request == 1) { + UE->is_synchronized = 0; + // if upper layers signal BW scan we do as instructed by command line parameter + // if upper layers disable BW scan we set it to false + if (UE->synch_request.synch_req.ssb_bw_scan) + UE->UE_scan_carrier = get_nrUE_params()->UE_scan_carrier; + else + UE->UE_scan_carrier = false; + UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell; + + const fapi_nr_ue_carrier_config_t *cfg = &UE->nrUE_config.carrier_config; + uint64_t dl_CarrierFreq = get_carrier_frequency(fp->N_RB_DL, fp->numerology_index, cfg->dl_frequency); + uint64_t ul_CarrierFreq = get_carrier_frequency(fp->N_RB_UL, fp->numerology_index, cfg->uplink_frequency); + if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) { + fp->dl_CarrierFreq = dl_CarrierFreq; + fp->ul_CarrierFreq = ul_CarrierFreq; + nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0); + UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &openair0_cfg[0]); + init_symbol_rotation(fp); + } + + clean_UE_harq(UE); + UE->synch_request.received_synch_request = 0; + return 0; + } + return 1; +} + static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc, int *tx_wait_for_dlsch, @@ -578,34 +610,6 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params; if (IS_SOFTMODEM_NOS1 || IS_SA_MODE(get_softmodem_params())) { - // Start synchronization with a target gNB - if (UE->synch_request.received_synch_request == 1) { - fapi_nr_synch_request_t *synch_req = &UE->synch_request.synch_req; - UE->is_synchronized = 0; - // if upper layers signal BW scan we do as instructed by command line parameter - // if upper layers disable BW scan we set it to false - if (UE->synch_request.synch_req.ssb_bw_scan) - UE->UE_scan_carrier = get_nrUE_params()->UE_scan_carrier; - else - UE->UE_scan_carrier = false; - UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell; - UE->target_Nid_cell = synch_req->target_Nid_cell; - - const fapi_nr_ue_carrier_config_t *cfg = &UE->nrUE_config.carrier_config; - uint64_t dl_CarrierFreq = get_carrier_frequency(fp->N_RB_DL, fp->numerology_index, cfg->dl_frequency); - uint64_t ul_CarrierFreq = get_carrier_frequency(fp->N_RB_UL, fp->numerology_index, cfg->uplink_frequency); - if (dl_CarrierFreq != fp->dl_CarrierFreq || ul_CarrierFreq != fp->ul_CarrierFreq) { - fp->dl_CarrierFreq = dl_CarrierFreq; - fp->ul_CarrierFreq = ul_CarrierFreq; - nr_rf_card_config_freq(&openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0); - UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &openair0_cfg[0]); - init_symbol_rotation(fp); - } - - clean_UE_harq(UE); - UE->synch_request.received_synch_request = 0; - } - /* send tick to RLC and PDCP every ms */ if (proc->nr_slot_rx % fp->slots_per_subframe == 0) { void nr_rlc_tick(int frame, int subframe); @@ -936,6 +940,10 @@ void *UE_thread(void *arg) continue; } + /* check if MAC has sent sync request */ + if (handle_sync_req_from_mac(UE) == 0) + continue; + // start of normal case, the UE is in sync absolute_slot++; TracyCFrameMark; From 73921dfa10496df718d5924cfad1e768f799ed87 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 3 Dec 2024 10:47:30 -0500 Subject: [PATCH 4/4] Prevent race condition when sync req received Added a flush mechanism to actor thread. This is used to wait for all waiting jobs in the queue to be completed. --- common/utils/actor/actor.c | 14 +++++++++++++- common/utils/actor/actor.h | 5 +++++ executables/nr-ue.c | 9 ++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/common/utils/actor/actor.c b/common/utils/actor/actor.c index 68661ddb6d..de4022e40b 100644 --- a/common/utils/actor/actor.c +++ b/common/utils/actor/actor.c @@ -50,7 +50,8 @@ void *actor_thread(void *arg) break; } - elt->processingFunc(NotifiedFifoData(elt)); + if (elt->processingFunc) // processing function can be NULL + elt->processingFunc(NotifiedFifoData(elt)); if (elt->reponseFifo) { pushNotifiedFIFO(elt->reponseFifo, elt); } else @@ -85,3 +86,14 @@ void shutdown_actor(Actor_t *actor) abortNotifiedFIFO(&response_fifo); pthread_join(actor->thread, NULL); } + +void flush_actor(Actor_t *actor) +{ + notifiedFIFO_t response_fifo; + initNotifiedFIFO(&response_fifo); + notifiedFIFO_elt_t *elt = newNotifiedFIFO_elt(0, 0, &response_fifo, NULL); + pushNotifiedFIFO(&actor->fifo, elt); + elt = pullNotifiedFIFO(&response_fifo); + delNotifiedFIFO_elt(elt); + abortNotifiedFIFO(&response_fifo); +} diff --git a/common/utils/actor/actor.h b/common/utils/actor/actor.h index 474554c667..023533d2d7 100644 --- a/common/utils/actor/actor.h +++ b/common/utils/actor/actor.h @@ -49,4 +49,9 @@ void destroy_actor(Actor_t *actor); /// @param actor void shutdown_actor(Actor_t *actor); +/// @brief This function will return when all current jobs in the queue are finished. +/// The caller should make sure no new jobs are added to the queue between this function call and return. +/// @param actor +void flush_actor(Actor_t *actor); + #endif diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 1dd1836fa7..1c4fc33344 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -570,7 +570,6 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE) NR_DL_FRAME_PARMS *fp = &UE->frame_parms; // Start synchronization with a target gNB if (UE->synch_request.received_synch_request == 1) { - UE->is_synchronized = 0; // if upper layers signal BW scan we do as instructed by command line parameter // if upper layers disable BW scan we set it to false if (UE->synch_request.synch_req.ssb_bw_scan) @@ -590,7 +589,15 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE) init_symbol_rotation(fp); } + /* Clearing UE harq while DL actors are active causes race condition. + So we let the current execution to complete here.*/ + for (int i = 0; i < NUM_DL_ACTORS; i++) { + flush_actor(UE->dl_actors + i); + } + /*TODO: Flush UL jobs */ + clean_UE_harq(UE); + UE->is_synchronized = 0; UE->synch_request.received_synch_request = 0; return 0; }