Merge remote-tracking branch 'origin/nfapi-fixes' into integration_2025_w04 (!2999)

Repair nFAPI in 5G

Add 5G nFAPI in OAI/Make it it work.

Many commits in this branch are basically bug fixes of things that don't work
properly, such as

- check for correct conditions (e.g. instance numbers in the RAN context)
- remove artificial limitation (e.g. only one PUCCH per TDD period in the PNF)
- improve performance (reduce big mallocs, make some static buffers such as a
  global ring buffer for nFAPI messages in the PNF)
- fix bugs in nFAPI (e.g., increase maximum message size to ~64kB instead of
  1500 bytes, because the latter is way too small for many TX_data.requests in
  5G, and it will delay message arrival unduly)
- fix bugs in message enc/dec (e.g., handle FDD in config.request)
- adjust the L1 such that the condition "we run monolithic" is not necessery
  (e.g., some message numbers in nFAPI struct where reset in MAC, instead of
  L1, and this breaks when running the PNF)

There are instructions that explain how to set it up. Two CI tests have been
added, one with COTS UE and MIMO in DL+UL in TDD numerology 1 (30kHz), and a
second test with FDD mu=0 (15kHZ) in RFsimulator.

These were some old to-dos that have been addressed.

- test with COTS UE - 4x4 pipeline works good in DL, UL now also work
- test in RFsim
- make PNF status message
- make FDD in u0 work
This commit is contained in:
Jaroslava Fiedlerova
2025-01-27 15:46:19 +01:00
80 changed files with 2104 additions and 21998 deletions
+9
View File
@@ -195,6 +195,15 @@ void handle_nr_srs_measurements(const module_id_t module_id,
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
/* TODO these declarations are to be removed */
void nr_schedule_dl_tti_req(void) {};
void nr_schedule_ul_dci_req() {};
void nr_schedule_tx_req() {};
void nr_schedule_ul_tti_req() {};
void nr_slot_select() {};
void NR_UL_indication(NR_UL_IND_t *UL_INFO) {};
void gNB_dlsch_ulsch_scheduler() {};
/*---------------------BMC: timespec helpers -----------------------------*/
struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
+6
View File
@@ -155,6 +155,12 @@ double cpuf;
extern char uecap_xer[1024];
char uecap_xer_in=0;
/* TODO these declarations are to be removed */
void nr_schedule_dl_tti_req(void) {};
void nr_schedule_ul_dci_req() {};
void nr_schedule_tx_req() {};
void nr_schedule_ul_tti_req() {};
void nr_slot_select() {};
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
* this is very hackish - find a proper solution
+18 -18
View File
@@ -138,9 +138,14 @@ static void tx_func(processingData_L1tx_t *info)
ru_tx_func((void *)&syncMsgRU);
stop_meas(&info->gNB->phy_proc_tx);
}
/* this thread is done with the sched_info, decrease the reference counter */
LOG_D(NR_PHY, "Calling deref_sched_response for id %d (tx_func) in %d.%d\n", info->sched_response_id, frame_tx, slot_tx);
deref_sched_response(info->sched_response_id);
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
/* this thread is done with the sched_info, decrease the reference counter.
* This only applies for monolithic; in the PNF, the memory is allocated in
* a ring buffer that should never be overwritten (one frame duration). */
LOG_D(NR_PHY, "Calling deref_sched_response for id %d (tx_func) in %d.%d\n", info->sched_response_id, frame_tx, slot_tx);
deref_sched_response(info->sched_response_id);
}
}
void *L1_rx_thread(void *arg)
@@ -179,15 +184,6 @@ static void rx_func(processingData_L1_t *info)
int slot_rx = info->slot_rx;
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
// *******************************************************************
if (NFAPI_MODE == NFAPI_MODE_PNF) {
// I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
// LOG_D(PHY, "oai_nfapi_slot_ind(frame:%u, slot:%d) ********\n", frame_rx, slot_rx);
handle_nr_slot_ind(frame_rx, slot_rx);
}
// ****************************************
// RX processing
int rx_slot_type = nr_slot_select(cfg, frame_rx, slot_rx);
if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) {
@@ -312,7 +308,13 @@ void *nrL1_stats_thread(void *param) {
return(NULL);
}
void init_gNB_Tpool(int inst) {
void init_gNB_Tpool(int inst)
{
AssertFatal(NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MONOLITHIC,
"illegal NFAPI_MODE %d (%s): it cannot have an L1\n",
NFAPI_MODE,
nfapi_get_strmode());
PHY_VARS_gNB *gNB;
gNB = RC.gNB[inst];
gNB_L1_proc_t *proc = &gNB->proc;
@@ -345,8 +347,7 @@ void init_gNB_Tpool(int inst) {
// this will be removed when the msgDataTx is not necessary anymore
gNB->msgDataTx = msgDataTx;
if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS) && (NFAPI_MODE != NFAPI_MODE_VNF)
&& (NFAPI_MODE != NFAPI_MODE_AERIAL))
if (!IS_SOFTMODEM_NOSTATS)
threadCreate(&proc->L1_stats_thread, nrL1_stats_thread, (void *)gNB, "L1_stats", -1, OAI_PRIORITY_RT_LOW);
}
@@ -365,8 +366,7 @@ void term_gNB_Tpool(int inst) {
abortNotifiedFIFO(&gNB->L1_rx_out);
gNB_L1_proc_t *proc = &gNB->proc;
if (!get_softmodem_params()->emulate_l1)
pthread_join(proc->L1_stats_thread, NULL);
pthread_join(proc->L1_stats_thread, NULL);
}
/// eNB kept in function name for nffapi calls, TO FIX
@@ -374,7 +374,7 @@ void init_eNB_afterRU(void) {
int inst,ru_id,i,aa;
PHY_VARS_gNB *gNB;
for (inst=0; inst<RC.nb_nr_inst; inst++) {
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
gNB = RC.gNB[inst];
phy_init_nr_gNB(gNB);
-22
View File
@@ -1200,29 +1200,7 @@ void *ru_thread(void *param)
struct timespec slot_start;
clock_gettime(CLOCK_MONOTONIC, &slot_start);
struct timespec slot_duration;
slot_duration.tv_sec = 0;
//slot_duration.tv_nsec = 0.5e6;
slot_duration.tv_nsec = 0.5e6;
while (!oai_exit) {
if (NFAPI_MODE==NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL ) {
// We should make a VNF main loop with proper tasks calls in case of VNF
slot_start = timespec_add(slot_start,slot_duration);
struct timespec curr_time;
clock_gettime(CLOCK_MONOTONIC, &curr_time);
struct timespec sleep_time;
if((slot_start.tv_sec > curr_time.tv_sec) ||
(slot_start.tv_sec == curr_time.tv_sec && slot_start.tv_nsec > curr_time.tv_nsec)){
sleep_time = timespec_sub(slot_start,curr_time);
usleep(sleep_time.tv_nsec * 1e-3);
}
}
if (slot==(fp->slots_per_frame-1)) {
slot=0;
frame++;
+14 -11
View File
@@ -678,26 +678,29 @@ int main( int argc, char **argv ) {
#endif // E2_AGENT
// wait for F1 Setup Response before starting L1 for real
if (NFAPI_MODE != NFAPI_MODE_PNF && (NODE_IS_DU(node_type) || NODE_IS_MONOLITHIC(node_type)))
wait_f1_setup_response();
if (RC.nb_RU > 0)
start_NR_RU();
#ifdef ENABLE_AERIAL
gNB_MAC_INST *nrmac = RC.nrmac[0];
nvIPC_Init(nrmac->nvipc_params_s);
#endif
for (int idx = 0; idx < RC.nb_nr_L1_inst; idx++)
RC.gNB[idx]->if_inst->sl_ahead = sl_ahead;
if (NFAPI_MODE==NFAPI_MODE_PNF) {
wait_nfapi_init("main?");
}
// wait for F1 Setup Response before starting L1 for real
if (NODE_IS_DU(node_type) || NODE_IS_MONOLITHIC(node_type))
wait_f1_setup_response();
if (RC.nb_RU > 0)
start_NR_RU();
#ifdef ENABLE_AERIAL
gNB_MAC_INST *nrmac = RC.nrmac[0];
nvIPC_Init(nrmac->nvipc_params_s);
#endif
if (RC.nb_nr_L1_inst > 0) {
wait_RUs();
// once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
for (int idx=0;idx<RC.nb_nr_L1_inst;idx++) RC.gNB[idx]->if_inst->sl_ahead = sl_ahead;
if (IS_SOFTMODEM_DOSCOPE || IS_SOFTMODEM_IMSCOPE_ENABLED) {
sleep(1);
scopeParms_t p;
+20 -14
View File
@@ -190,17 +190,21 @@ void init_nrUE_standalone_thread(int ue_idx)
pthread_setname_np(phy_thread, "oai:nrue-stand-phy");
}
static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn_slot)
static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn, int slot)
{
struct sfn_slot_s sfn_slot = {.sfn = sfn, .slot = slot};
nfapi_nr_rach_indication_t *rach_ind = unqueue_matching(&nr_rach_ind_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &sfn_slot);
nfapi_nr_dl_tti_request_t *dl_tti_request = get_queue(&nr_dl_tti_req_queue);
nfapi_nr_ul_dci_request_t *ul_dci_request = get_queue(&nr_ul_dci_req_queue);
for (int i = 0; i < NR_MAX_HARQ_PROCESSES; i++) {
LOG_D(NR_MAC, "Try to get a ul_tti_req by matching CRC active SFN %d/SLOT %d from queue with %lu items\n",
NFAPI_SFNSLOT2SFN(mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn_slot),
NFAPI_SFNSLOT2SLOT(mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn_slot), nr_ul_tti_req_queue.num_items);
nfapi_nr_ul_tti_request_t *ul_tti_request_crc = unqueue_matching(&nr_ul_tti_req_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn_slot);
LOG_D(NR_MAC,
"Try to get a ul_tti_req by matching CRC active sfn/slot %d.%d from queue with %lu items\n",
sfn,
slot,
nr_ul_tti_req_queue.num_items);
struct sfn_slot_s sfn_sf = {.sfn = mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn, .slot = mac->nr_ue_emul_l1.harq[i].active_ul_harq_slot };
nfapi_nr_ul_tti_request_t *ul_tti_request_crc = unqueue_matching(&nr_ul_tti_req_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &sfn_sf);
if (ul_tti_request_crc && ul_tti_request_crc->n_pdus > 0) {
check_and_process_dci(NULL, NULL, NULL, ul_tti_request_crc);
free_and_zero(ul_tti_request_crc);
@@ -216,11 +220,11 @@ static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn_slot)
free_and_zero(rach_ind);
}
if (dl_tti_request) {
int dl_tti_sfn_slot = NFAPI_SFNSLOT2HEX(dl_tti_request->SFN, dl_tti_request->Slot);
nfapi_nr_tx_data_request_t *tx_data_request = unqueue_matching(&nr_tx_req_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &dl_tti_sfn_slot);
struct sfn_slot_s sfn_slot = {.sfn = dl_tti_request->SFN, .slot = dl_tti_request->Slot};
nfapi_nr_tx_data_request_t *tx_data_request = unqueue_matching(&nr_tx_req_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &sfn_slot);
if (!tx_data_request) {
LOG_E(NR_MAC, "[%d %d] No corresponding tx_data_request for given dl_tti_request sfn/slot\n",
NFAPI_SFNSLOT2SFN(dl_tti_sfn_slot), NFAPI_SFNSLOT2SLOT(dl_tti_sfn_slot));
LOG_E(NR_MAC, "[%d.%d] No corresponding tx_data_request for given dl_tti_request sfn/slot\n",
dl_tti_request->SFN, dl_tti_request->Slot);
if (get_softmodem_params()->nsa)
save_nr_measurement_info(dl_tti_request);
free_and_zero(dl_tti_request);
@@ -262,7 +266,8 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
for (int i = 0; i < NR_MAX_HARQ_PROCESSES; i++) {
mac->nr_ue_emul_l1.harq[i].active = false;
mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn_slot = -1;
mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn = -1;
mac->nr_ue_emul_l1.harq[i].active_ul_harq_slot = -1;
}
while (!oai_exit) {
@@ -285,8 +290,9 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
free_and_zero(ch_info);
}
frame_t frame = NFAPI_SFNSLOT2SFN(sfn_slot);
int slot = NFAPI_SFNSLOT2SLOT(sfn_slot);
int mu = 1; // NR-UE emul-L1 is hardcoded to 30kHZ, see check_and_process_dci()
frame_t frame = NFAPI_SFNSLOTDEC2SFN(mu, sfn_slot);
int slot = NFAPI_SFNSLOTDEC2SLOT(mu, sfn_slot);
if (sfn_slot == last_sfn_slot) {
LOG_D(NR_MAC, "repeated sfn_sf = %d.%d\n",
frame, slot);
@@ -300,7 +306,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
if (IS_SA_MODE(get_softmodem_params()) && mac->mib == NULL) {
LOG_D(NR_MAC, "We haven't gotten MIB. Lets see if we received it\n");
nr_ue_dl_indication(&mac->dl_info);
process_queued_nr_nfapi_msgs(mac, sfn_slot);
process_queued_nr_nfapi_msgs(mac, frame, slot);
}
int CC_id = 0;
@@ -340,7 +346,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
LOG_D(NR_MAC, "Slot %d. calling nr_ue_ul_ind()\n", ul_info.slot);
nr_ue_ul_scheduler(mac, &ul_info);
}
process_queued_nr_nfapi_msgs(mac, sfn_slot);
process_queued_nr_nfapi_msgs(mac, frame, slot);
}
return NULL;
}