From f393300da15bead87bf3f30dbfa4c0dbd4e8bf5d Mon Sep 17 00:00:00 2001 From: Shubhika Garg Date: Fri, 30 Jan 2026 10:11:21 +0100 Subject: [PATCH 01/17] RHEL: switch registry to registry.redhat.io - Switched base image source from registry.access.redhat.com to registry.redhat.io for all RHEL9 variants. --- docker/Dockerfile.base.rhel9 | 2 +- docker/Dockerfile.eNB.rhel9 | 2 +- docker/Dockerfile.gNB.aw2s.rhel9 | 2 +- docker/Dockerfile.gNB.fhi72.rhel9 | 2 +- docker/Dockerfile.gNB.rhel9 | 2 +- docker/Dockerfile.lteRU.rhel9 | 2 +- docker/Dockerfile.lteUE.rhel9 | 2 +- docker/Dockerfile.nr-cuup.rhel9 | 2 +- docker/Dockerfile.nrUE.rhel9 | 2 +- docker/Dockerfile.phySim.rhel9 | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docker/Dockerfile.base.rhel9 b/docker/Dockerfile.base.rhel9 index e57c705471..d21a6b09fd 100644 --- a/docker/Dockerfile.base.rhel9 +++ b/docker/Dockerfile.base.rhel9 @@ -26,7 +26,7 @@ #--------------------------------------------------------------------- -FROM registry.access.redhat.com/ubi9/ubi:latest AS ran-base +FROM registry.redhat.io/ubi9/ubi:latest AS ran-base LABEL MAINTAINER OpenAirInterface ARG NEEDED_GIT_PROXY ARG TARGETARCH diff --git a/docker/Dockerfile.eNB.rhel9 b/docker/Dockerfile.eNB.rhel9 index 3cd1018634..240456c0fe 100644 --- a/docker/Dockerfile.eNB.rhel9 +++ b/docker/Dockerfile.eNB.rhel9 @@ -31,7 +31,7 @@ FROM ran-build:latest AS enb-build #start from scratch for target executable -FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-enb +FROM registry.redhat.io/ubi9/ubi:latest AS oai-enb ENV TZ=Europe/Paris RUN dnf update -y && \ diff --git a/docker/Dockerfile.gNB.aw2s.rhel9 b/docker/Dockerfile.gNB.aw2s.rhel9 index e35b0a7690..155429e4e3 100644 --- a/docker/Dockerfile.gNB.aw2s.rhel9 +++ b/docker/Dockerfile.gNB.aw2s.rhel9 @@ -38,7 +38,7 @@ RUN /bin/sh oaienv && \ ./build_oai -w AW2SORI -t Ethernet #start from scratch for target executable -FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-gnb-aw2s +FROM registry.redhat.io/ubi9/ubi:latest AS oai-gnb-aw2s ENV TZ=Europe/Paris # Install EPEL for RHEL9 diff --git a/docker/Dockerfile.gNB.fhi72.rhel9 b/docker/Dockerfile.gNB.fhi72.rhel9 index bda79eba28..bbcfe7b42d 100644 --- a/docker/Dockerfile.gNB.fhi72.rhel9 +++ b/docker/Dockerfile.gNB.fhi72.rhel9 @@ -30,7 +30,7 @@ FROM ran-base:latest AS gnb-base FROM ran-build-fhi72:latest AS gnb-build #start from scratch for target executable -FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-gnb-fhi72 +FROM registry.redhat.io/ubi9/ubi:latest AS oai-gnb-fhi72 ENV TZ=Europe/Paris # Install EPEL for RHEL9 diff --git a/docker/Dockerfile.gNB.rhel9 b/docker/Dockerfile.gNB.rhel9 index 4e766bd011..0eb347dc64 100644 --- a/docker/Dockerfile.gNB.rhel9 +++ b/docker/Dockerfile.gNB.rhel9 @@ -31,7 +31,7 @@ FROM ran-build:latest AS gnb-build #start from scratch for target executable -FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-gnb +FROM registry.redhat.io/ubi9/ubi:latest AS oai-gnb ENV TZ=Europe/Paris # Install EPEL for RHEL9 diff --git a/docker/Dockerfile.lteRU.rhel9 b/docker/Dockerfile.lteRU.rhel9 index 736ae2a884..ba36e36b3d 100644 --- a/docker/Dockerfile.lteRU.rhel9 +++ b/docker/Dockerfile.lteRU.rhel9 @@ -31,7 +31,7 @@ FROM ran-build:latest AS ru-build #start from scratch for target executable -FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-lte-ru +FROM registry.redhat.io/ubi9/ubi:latest AS oai-lte-ru ENV TZ=Europe/Paris RUN dnf update -y && \ diff --git a/docker/Dockerfile.lteUE.rhel9 b/docker/Dockerfile.lteUE.rhel9 index 7f1199c897..6dee43cbac 100644 --- a/docker/Dockerfile.lteUE.rhel9 +++ b/docker/Dockerfile.lteUE.rhel9 @@ -31,7 +31,7 @@ FROM ran-build:latest AS lte-ue-build #start from scratch for target executable -FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-lte-ue +FROM registry.redhat.io/ubi9/ubi:latest AS oai-lte-ue ENV TZ=Europe/Paris RUN dnf update -y && \ diff --git a/docker/Dockerfile.nr-cuup.rhel9 b/docker/Dockerfile.nr-cuup.rhel9 index e21c084c52..e87b89e362 100644 --- a/docker/Dockerfile.nr-cuup.rhel9 +++ b/docker/Dockerfile.nr-cuup.rhel9 @@ -32,7 +32,7 @@ FROM ran-build:latest AS gnb-build RUN cp /oai-ran/docker/scripts/gnb_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh #start from scratch for target executable -FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-nr-cuup +FROM registry.redhat.io/ubi9/ubi:latest AS oai-nr-cuup ENV TZ=Europe/Paris # Install EPEL diff --git a/docker/Dockerfile.nrUE.rhel9 b/docker/Dockerfile.nrUE.rhel9 index 79f44dfafb..3a55825f7a 100644 --- a/docker/Dockerfile.nrUE.rhel9 +++ b/docker/Dockerfile.nrUE.rhel9 @@ -31,7 +31,7 @@ FROM ran-build:latest AS nr-ue-build #start from scratch for target executable -FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-nr-ue +FROM registry.redhat.io/ubi9/ubi:latest AS oai-nr-ue ENV TZ=Europe/Paris # Install EPEL for RHEL9 diff --git a/docker/Dockerfile.phySim.rhel9 b/docker/Dockerfile.phySim.rhel9 index eb6d92d78c..40db199bd4 100644 --- a/docker/Dockerfile.phySim.rhel9 +++ b/docker/Dockerfile.phySim.rhel9 @@ -46,7 +46,7 @@ RUN /bin/sh oaienv && \ ninja -k10 -j36 #start from scratch for target executable -FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-physim +FROM registry.redhat.io/ubi9/ubi:latest AS oai-physim RUN dnf update -y && \ dnf install -y \ From 003d72c8591018acdbbb78355b52ee8dfd516f31 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Tue, 28 Oct 2025 16:35:59 +0800 Subject: [PATCH 02/17] fhi7.2: introduce support for T1a and Ta4 values larger than TTI interval In xRAN, it appears that T1a/Ta4 values are assumed to be within a TTI. When T1a/Ta4 values with larger than a TTI are used, this causes two issues: (1) C-plane packets to be generated later than expected and (2) oai_xran_fh_rx_callback() receives the wrong timing information resulting in potentially empty/stale PUSCH/PRACH data to be read. In this patch, we modify xRAN to make it handle large T1a/Ta4 values properly. The changes include: (1) three additional variables in offset_num_slots_* (xran_dev.h), (2) modify "xran_timing_create_cbs" and "xran_timer_arm_for_deadline" (xran_cb_proc.c), and (3) revise "tx_cp_dl_cb" and "tx_cp_ul_cb" (xran_main.c). Additionally, we add additional guard conditions to prevent xran_tx_proc.c from sending U-plane packets when it is not a downlink slot. --- .../F/oaioran_F.patch | 304 +++++++++++++----- radio/fhi_72/CMakeLists.txt | 2 +- 2 files changed, 226 insertions(+), 80 deletions(-) diff --git a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch index ba10bf38af..c30c6bd8fa 100644 --- a/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch +++ b/cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch @@ -1,5 +1,5 @@ diff --git a/fhi_lib/app/src/common.h b/fhi_lib/app/src/common.h -index ac5f471..ed9ab7d 100644 +index ac5f471..b1acb26 100644 --- a/fhi_lib/app/src/common.h +++ b/fhi_lib/app/src/common.h @@ -28,7 +28,7 @@ @@ -7,7 +7,7 @@ index ac5f471..ed9ab7d 100644 #include -#define VERSIONX "oran_f_release_v1.0" -+#define VERSIONX "oran_f_release_v1.7" ++#define VERSIONX "oran_f_release_v1.8" #define APP_O_DU 0 #define APP_O_RU 1 @@ -530,7 +530,7 @@ index 59b6850..322d238 100644 \ No newline at end of file +} diff --git a/fhi_lib/lib/src/xran_cb_proc.c b/fhi_lib/lib/src/xran_cb_proc.c -index 08660f3..2bb5187 100644 +index 08660f3..b5de607 100644 --- a/fhi_lib/lib/src/xran_cb_proc.c +++ b/fhi_lib/lib/src/xran_cb_proc.c @@ -25,7 +25,10 @@ @@ -544,6 +544,55 @@ index 08660f3..2bb5187 100644 #include #include #include +@@ -106,6 +109,12 @@ void xran_timer_arm_for_deadline(struct rte_timer *tim, void* arg, void *p_dev_ + + nSubframeIdx*SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local) + + nSlotIdx; + ++ /* correction to rx_tti for Ta4 values larger than a TTI */ ++ rx_tti -= p_xran_dev_ctx->offset_num_slots_up_ul; ++ if (rx_tti < 0) { ++ rx_tti += (SUBFRAMES_PER_SYSTEMFRAME*SLOTNUM_PER_SUBFRAME(p_xran_dev_ctx->interval_us_local)*1024); ++ } ++ + p_xran_dev_ctx->cb_timer_ctx[p_xran_dev_ctx->timer_put % MAX_CB_TIMER_CTX].tti_to_process = rx_tti; + if (xran_if_current_state == XRAN_RUNNING){ + rte_timer_cb_t fct = (rte_timer_cb_t)arg; +@@ -195,6 +204,7 @@ xran_timing_create_cbs(void *args) + max_dl_delay_offset += interval_us_local; + numSlots++; + } ++ p_dev_ctx->offset_num_slots_cp_dl = numSlots; + + /* Delay from start of 'a' slot */ + delay_cp_dl_max = max_dl_delay_offset - p_dev_ctx->fh_cfg.T1a_max_cp_dl; +@@ -227,6 +237,7 @@ xran_timing_create_cbs(void *args) + ul_delay_offset += interval_us_local; + numSlots++; + } ++ p_dev_ctx->offset_num_slots_cp_ul = numSlots; + delay_cp_ul = ul_delay_offset - p_dev_ctx->fh_cfg.T1a_max_cp_ul; + sym_cp_ul = (delay_cp_ul*1000/(interval_us_local*1000/N_SYM_PER_SLOT)+1); + uint8_t ul_offset_sym = (numSlots+1)*N_SYM_PER_SLOT - sym_cp_ul; +@@ -242,8 +253,18 @@ xran_timing_create_cbs(void *args) + + delay_up = p_dev_ctx->fh_cfg.T1a_max_up; + time_diff_us = p_dev_ctx->fh_cfg.Ta4_max; ++ uint32_t ul_up_delay_offset=interval_us_local; ++ numSlots=0; ++ while(time_diff_us > ul_up_delay_offset) { ++ ul_up_delay_offset += interval_us_local; ++ numSlots++; ++ } ++ p_dev_ctx->offset_num_slots_up_ul = numSlots; ++ ++ printf("offset_num_slots_cp_dl=%d, offset_num_slots_cp_ul=%d, offset_num_slots_up_ul=%d\n", ++ p_dev_ctx->offset_num_slots_cp_dl, p_dev_ctx->offset_num_slots_cp_ul, p_dev_ctx->offset_num_slots_up_ul); + +- delay_cp2up = delay_up-delay_cp_dl_max; ++ delay_cp2up = p_dev_ctx->fh_cfg.T1a_max_cp_dl - p_dev_ctx->fh_cfg.T1a_max_up; + + + time_diff_nSymb = time_diff_us*1000/(interval_us_local*1000/N_SYM_PER_SLOT); diff --git a/fhi_lib/lib/src/xran_common.c b/fhi_lib/lib/src/xran_common.c index dc40ad9..1b88013 100644 --- a/fhi_lib/lib/src/xran_common.c @@ -1032,7 +1081,7 @@ index 4acade1..c939edc 100644 for(i = 0; i < xran_ports_num; i++){ g_xran_dev_ctx[i] = pCtx; diff --git a/fhi_lib/lib/src/xran_dev.h b/fhi_lib/lib/src/xran_dev.h -index 0371a53..dd76b49 100644 +index 0371a53..778b38d 100644 --- a/fhi_lib/lib/src/xran_dev.h +++ b/fhi_lib/lib/src/xran_dev.h @@ -201,6 +201,7 @@ struct __rte_cache_aligned xran_device_ctx @@ -1043,6 +1092,18 @@ index 0371a53..dd76b49 100644 int64_t offset_sec; int64_t offset_nsec; //offset to GPS time calcuated based on alpha and beta uint32_t interval_us_local; +@@ -254,6 +255,11 @@ struct __rte_cache_aligned xran_device_ctx + int32_t sym_up; /**< when we start sym 0 of up with respect to OTA time as measured in symbols */ + int32_t sym_up_ul; + ++ /* used to support large T1a/Ta4 values */ ++ int32_t offset_num_slots_cp_dl; ++ int32_t offset_num_slots_cp_ul; ++ int32_t offset_num_slots_up_ul; ++ + xran_fh_tti_callback_fn ttiCb[XRAN_CB_MAX]; + void *TtiCbParam[XRAN_CB_MAX]; + uint32_t SkipTti[XRAN_CB_MAX]; diff --git a/fhi_lib/lib/src/xran_frame_struct.c b/fhi_lib/lib/src/xran_frame_struct.c index fbb1298..44aaf92 100644 --- a/fhi_lib/lib/src/xran_frame_struct.c @@ -1082,7 +1143,7 @@ index 7ed0a3a..8e66945 100644 #ifdef __cplusplus } diff --git a/fhi_lib/lib/src/xran_main.c b/fhi_lib/lib/src/xran_main.c -index 7c472d7..7c7cf91 100644 +index 7c472d7..db03d94 100644 --- a/fhi_lib/lib/src/xran_main.c +++ b/fhi_lib/lib/src/xran_main.c @@ -35,7 +35,11 @@ @@ -1132,7 +1193,42 @@ index 7c472d7..7c7cf91 100644 print_dbg("PRACH eAxC_offset %d\n", pPrachCPConfig->eAxC_offset); /* Save some configs for app */ -@@ -1169,6 +1192,10 @@ xran_prepare_cp_ul_slot(uint16_t xran_port_id, uint32_t nSlotIdx, uint32_t nCcS +@@ -623,6 +646,8 @@ xran_prepare_cp_dl_slot(uint16_t xran_port_id, uint32_t nSlotIdx, uint32_t nCcS + return ret; + } + ++uint32_t prev_dl_tti = -1; ++ + void + tx_cp_dl_cb(struct rte_timer *tim, void *arg) + { +@@ -655,7 +680,7 @@ tx_cp_dl_cb(struct rte_timer *tim, void *arg) + + if(first_call && p_xran_dev_ctx->enableCP) + { +- tti = pTCtx[(xran_lib_ota_tti[PortId] & 1) ^ 1].tti_to_process; ++ tti = pTCtx[(xran_lib_ota_tti[PortId] & 1) ^ 1].tti_to_process + p_xran_dev_ctx->offset_num_slots_cp_dl; + buf_id = tti % XRAN_N_FE_BUF_LEN; + + slot_id = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME(interval_us_local)); +@@ -665,6 +690,16 @@ tx_cp_dl_cb(struct rte_timer *tim, void *arg) + { + /* Wrap around to next second */ + frame_id = (frame_id + NUM_OF_FRAMES_PER_SECOND) & 0x3ff; ++ prev_dl_tti = -1; ++ } ++ else if (p_xran_dev_ctx->offset_num_slots_cp_dl > 0 && prev_dl_tti == xran_fs_get_max_slot(PortId) - 1 + p_xran_dev_ctx->offset_num_slots_cp_dl) ++ { ++ prev_dl_tti = tti; ++ tti = xran_fs_get_max_slot(PortId) + p_xran_dev_ctx->offset_num_slots_cp_dl; ++ } ++ else ++ { ++ prev_dl_tti = tti; + } + + ctx_id = tti % XRAN_MAX_SECTIONDB_CTX; +@@ -1169,6 +1204,10 @@ xran_prepare_cp_ul_slot(uint16_t xran_port_id, uint32_t nSlotIdx, uint32_t nCcS uint8_t seqid = xran_get_cp_seqid(pHandle, XRAN_DIR_UL, cc_id, port_id); beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, port_id, slot_id); @@ -1143,7 +1239,45 @@ index 7c472d7..7c7cf91 100644 ret = generate_cpmsg_prach(pHandle, ¶ms, sect_geninfo, mbuf, p_xran_dev_ctx, frame_id, subframe_id, slot_id, tti, beam_id, cc_id, port_id, occasionid, seqid); -@@ -1338,6 +1365,10 @@ tx_cp_ul_cb(struct rte_timer *tim, void *arg) +@@ -1213,6 +1252,7 @@ xran_prepare_cp_ul_slot(uint16_t xran_port_id, uint32_t nSlotIdx, uint32_t nCcS + return ret; + } + ++uint32_t prev_ul_tti = -1; + + void + tx_cp_ul_cb(struct rte_timer *tim, void *arg) +@@ -1254,7 +1294,7 @@ tx_cp_ul_cb(struct rte_timer *tim, void *arg) + pTCtx = &p_xran_dev_ctx->timer_ctx[0]; + interval = p_xran_dev_ctx->interval_us_local; + PortId = p_xran_dev_ctx->xran_port_id; +- tti = pTCtx[(xran_lib_ota_tti[PortId] & 1) ^ 1].tti_to_process; ++ tti = pTCtx[(xran_lib_ota_tti[PortId] & 1) ^ 1].tti_to_process + p_xran_dev_ctx->offset_num_slots_cp_ul; + + buf_id = tti % XRAN_N_FE_BUF_LEN; + ctx_id = tti % XRAN_MAX_SECTIONDB_CTX; +@@ -1264,7 +1304,20 @@ tx_cp_ul_cb(struct rte_timer *tim, void *arg) + + /* Wrap around to next second */ + if(tti == 0) ++ { + frame_id = (frame_id + NUM_OF_FRAMES_PER_SECOND) & 0x3ff; ++ prev_ul_tti = tti; ++ } ++ else if (p_xran_dev_ctx->offset_num_slots_cp_ul > 0 && prev_ul_tti == xran_fs_get_max_slot(PortId) - 1 + p_xran_dev_ctx->offset_num_slots_cp_ul) ++ { ++ prev_ul_tti = tti; ++ tti = xran_fs_get_max_slot(PortId) + p_xran_dev_ctx->offset_num_slots_cp_ul; ++ } ++ else ++ { ++ prev_ul_tti = tti; ++ } ++ + if(xran_get_ru_category(pHandle) == XRAN_CATEGORY_A) + num_eAxc = xran_get_num_eAxc(pHandle); + else +@@ -1338,6 +1391,10 @@ tx_cp_ul_cb(struct rte_timer *tim, void *arg) uint8_t seqid = xran_get_cp_seqid(pHandle, XRAN_DIR_UL, cc_id, port_id); beam_id = xran_get_beamid(pHandle, XRAN_DIR_UL, cc_id, port_id, slot_id); @@ -1154,7 +1288,7 @@ index 7c472d7..7c7cf91 100644 ret = generate_cpmsg_prach(pHandle, ¶ms, sect_geninfo, mbuf, p_xran_dev_ctx, frame_id, subframe_id, slot_id, tti, beam_id, cc_id, port_id, occasionid, seqid); -@@ -1570,6 +1601,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru +@@ -1570,6 +1627,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru { case ECPRI_IQ_DATA: pkt_data[num_data++] = pkt; @@ -1162,7 +1296,7 @@ index 7c472d7..7c7cf91 100644 break; // For RU emulation case ECPRI_RT_CONTROL_DATA: -@@ -1587,7 +1619,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru +@@ -1587,7 +1645,7 @@ int32_t handle_ecpri_ethertype(struct rte_mbuf* pkt_q[], uint16_t xport_id, stru break; default: if (p_dev_ctx->fh_init.io_cfg.id == O_DU) { @@ -1171,7 +1305,7 @@ index 7c472d7..7c7cf91 100644 } break; } -@@ -1876,7 +1908,7 @@ xran_sector_get_instances (uint32_t xran_port, void * pDevHandle, uint16_t nNumI +@@ -1876,7 +1934,7 @@ xran_sector_get_instances (uint32_t xran_port, void * pDevHandle, uint16_t nNumI for (i = 0; i < nNumInstances; i++) { /* Allocate Memory for CC handles */ @@ -1180,7 +1314,7 @@ index 7c472d7..7c7cf91 100644 if(pCcHandle == NULL) return XRAN_STATUS_RESOURCE; -@@ -2347,8 +2379,7 @@ ring_processing_func_per_port(void* args) +@@ -2347,8 +2405,7 @@ ring_processing_func_per_port(void* args) for (i = 0; i < ctx->io_cfg.num_vfs && i < XRAN_VF_MAX; i = i+1) { if (ctx->vf2xran_port[i] == port_id) { for(qi = 0; qi < ctx->rxq_per_port[port_id]; qi++){ @@ -1190,7 +1324,7 @@ index 7c472d7..7c7cf91 100644 } } } -@@ -2414,9 +2445,6 @@ xran_spawn_workers(void) +@@ -2414,9 +2471,6 @@ xran_spawn_workers(void) nWorkerCore = nWorkerCore << 1; } @@ -1200,7 +1334,7 @@ index 7c472d7..7c7cf91 100644 printf("O-XU %d\n", eth_ctx->io_cfg.id); printf("HW %d\n", icx_cpu); printf("Num cores %d\n", total_num_cores); -@@ -2453,7 +2481,7 @@ xran_spawn_workers(void) +@@ -2453,7 +2507,7 @@ xran_spawn_workers(void) eth_ctx->time_wrk_cfg.arg = NULL; eth_ctx->time_wrk_cfg.state = 1; @@ -1209,7 +1343,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2475,7 +2503,7 @@ xran_spawn_workers(void) +@@ -2475,7 +2529,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1218,7 +1352,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2502,7 +2530,7 @@ xran_spawn_workers(void) +@@ -2502,7 +2556,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1227,7 +1361,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2536,7 +2564,7 @@ xran_spawn_workers(void) +@@ -2536,7 +2590,7 @@ xran_spawn_workers(void) else p_dev->tx_sym_gen_func = xran_process_tx_sym_cp_on_opt; @@ -1236,7 +1370,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2559,7 +2587,7 @@ xran_spawn_workers(void) +@@ -2559,7 +2613,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1245,7 +1379,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2586,7 +2614,7 @@ xran_spawn_workers(void) +@@ -2586,7 +2640,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1254,7 +1388,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2613,7 +2641,7 @@ xran_spawn_workers(void) +@@ -2613,7 +2667,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1263,7 +1397,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2628,7 +2656,7 @@ xran_spawn_workers(void) +@@ -2628,7 +2682,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1272,7 +1406,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2643,7 +2671,7 @@ xran_spawn_workers(void) +@@ -2643,7 +2697,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1281,7 +1415,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2682,7 +2710,7 @@ xran_spawn_workers(void) +@@ -2682,7 +2736,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1290,7 +1424,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2697,7 +2725,7 @@ xran_spawn_workers(void) +@@ -2697,7 +2751,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1299,7 +1433,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2712,7 +2740,7 @@ xran_spawn_workers(void) +@@ -2712,7 +2766,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1308,7 +1442,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2727,7 +2755,7 @@ xran_spawn_workers(void) +@@ -2727,7 +2781,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 UP GEN **/ @@ -1317,7 +1451,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2766,7 +2794,7 @@ xran_spawn_workers(void) +@@ -2766,7 +2820,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1326,7 +1460,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2781,7 +2809,7 @@ xran_spawn_workers(void) +@@ -2781,7 +2835,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 Eth Tx **/ @@ -1335,7 +1469,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); -@@ -2797,7 +2825,7 @@ xran_spawn_workers(void) +@@ -2797,7 +2851,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 - CP GEN **/ @@ -1344,7 +1478,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2812,7 +2840,7 @@ xran_spawn_workers(void) +@@ -2812,7 +2866,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 UP GEN **/ @@ -1353,7 +1487,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2827,7 +2855,7 @@ xran_spawn_workers(void) +@@ -2827,7 +2881,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 4 UP GEN **/ @@ -1362,7 +1496,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2861,7 +2889,7 @@ xran_spawn_workers(void) +@@ -2861,7 +2915,7 @@ xran_spawn_workers(void) /* workers */ /** 0 Eth RX */ @@ -1371,7 +1505,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2876,7 +2904,7 @@ xran_spawn_workers(void) +@@ -2876,7 +2930,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 FH RX and BBDEV */ @@ -1380,7 +1514,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2891,7 +2919,7 @@ xran_spawn_workers(void) +@@ -2891,7 +2945,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 FH RX and BBDEV */ @@ -1389,7 +1523,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2906,7 +2934,7 @@ xran_spawn_workers(void) +@@ -2906,7 +2960,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 FH RX and BBDEV */ @@ -1398,7 +1532,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2921,7 +2949,7 @@ xran_spawn_workers(void) +@@ -2921,7 +2975,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** FH TX and BBDEV */ @@ -1407,7 +1541,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -2969,7 +2997,7 @@ xran_spawn_workers(void) +@@ -2969,7 +3023,7 @@ xran_spawn_workers(void) /* p_dev->tx_sym_gen_func = xran_process_tx_sym_cp_on_opt; */ @@ -1416,7 +1550,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3004,7 +3032,7 @@ xran_spawn_workers(void) +@@ -3004,7 +3058,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1425,7 +1559,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3031,7 +3059,7 @@ xran_spawn_workers(void) +@@ -3031,7 +3085,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1434,7 +1568,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3062,7 +3090,7 @@ xran_spawn_workers(void) +@@ -3062,7 +3116,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1443,7 +1577,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3089,7 +3117,7 @@ xran_spawn_workers(void) +@@ -3089,7 +3143,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1452,7 +1586,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3115,7 +3143,7 @@ xran_spawn_workers(void) +@@ -3115,7 +3169,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1461,7 +1595,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3130,7 +3158,7 @@ xran_spawn_workers(void) +@@ -3130,7 +3184,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1470,7 +1604,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3145,7 +3173,7 @@ xran_spawn_workers(void) +@@ -3145,7 +3199,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1479,7 +1613,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3184,7 +3212,7 @@ xran_spawn_workers(void) +@@ -3184,7 +3238,7 @@ xran_spawn_workers(void) /* workers */ /** 0 FH RX and BBDEV */ @@ -1488,7 +1622,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3199,7 +3227,7 @@ xran_spawn_workers(void) +@@ -3199,7 +3253,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1497,7 +1631,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3214,7 +3242,7 @@ xran_spawn_workers(void) +@@ -3214,7 +3268,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1506,7 +1640,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3229,7 +3257,7 @@ xran_spawn_workers(void) +@@ -3229,7 +3283,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 UP GEN **/ @@ -1515,7 +1649,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3266,7 +3294,7 @@ xran_spawn_workers(void) +@@ -3266,7 +3320,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1524,7 +1658,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3281,7 +3309,7 @@ xran_spawn_workers(void) +@@ -3281,7 +3335,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 - CP GEN **/ @@ -1533,7 +1667,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3296,7 +3324,7 @@ xran_spawn_workers(void) +@@ -3296,7 +3350,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1542,7 +1676,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3311,7 +3339,7 @@ xran_spawn_workers(void) +@@ -3311,7 +3365,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 UP GEN **/ @@ -1551,7 +1685,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3326,7 +3354,7 @@ xran_spawn_workers(void) +@@ -3326,7 +3380,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 4 UP GEN **/ @@ -1560,7 +1694,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3348,7 +3376,7 @@ xran_spawn_workers(void) +@@ -3348,7 +3402,7 @@ xran_spawn_workers(void) /* workers */ /** 0 Eth RX */ @@ -1569,7 +1703,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3363,7 +3391,7 @@ xran_spawn_workers(void) +@@ -3363,7 +3417,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 FH RX and BBDEV */ @@ -1578,7 +1712,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3378,7 +3406,7 @@ xran_spawn_workers(void) +@@ -3378,7 +3432,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 FH RX and BBDEV */ @@ -1587,7 +1721,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3393,7 +3421,7 @@ xran_spawn_workers(void) +@@ -3393,7 +3447,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 FH RX and BBDEV */ @@ -1596,7 +1730,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3408,7 +3436,7 @@ xran_spawn_workers(void) +@@ -3408,7 +3462,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** FH TX and BBDEV */ @@ -1605,7 +1739,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3435,7 +3463,7 @@ xran_spawn_workers(void) +@@ -3435,7 +3489,7 @@ xran_spawn_workers(void) /* workers */ /** 0 Eth RX */ @@ -1614,7 +1748,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3450,7 +3478,7 @@ xran_spawn_workers(void) +@@ -3450,7 +3504,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 1 FH RX and BBDEV */ @@ -1623,7 +1757,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3465,7 +3493,7 @@ xran_spawn_workers(void) +@@ -3465,7 +3519,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 FH RX and BBDEV */ @@ -1632,7 +1766,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3480,7 +3508,7 @@ xran_spawn_workers(void) +@@ -3480,7 +3534,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 3 FH RX and BBDEV */ @@ -1641,7 +1775,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3495,7 +3523,7 @@ xran_spawn_workers(void) +@@ -3495,7 +3549,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 4 FH RX and BBDEV */ @@ -1650,7 +1784,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3510,7 +3538,7 @@ xran_spawn_workers(void) +@@ -3510,7 +3564,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** FH TX and BBDEV */ @@ -1659,7 +1793,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3537,7 +3565,7 @@ xran_spawn_workers(void) +@@ -3537,7 +3591,7 @@ xran_spawn_workers(void) /* workers */ /** 0 **/ @@ -1668,7 +1802,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3562,7 +3590,7 @@ xran_spawn_workers(void) +@@ -3562,7 +3616,7 @@ xran_spawn_workers(void) } /** 1 - CP GEN **/ @@ -1677,7 +1811,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3577,7 +3605,7 @@ xran_spawn_workers(void) +@@ -3577,7 +3631,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 2 UP GEN **/ @@ -1686,7 +1820,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3602,7 +3630,7 @@ xran_spawn_workers(void) +@@ -3602,7 +3656,7 @@ xran_spawn_workers(void) } /** 3 UP GEN **/ @@ -1695,7 +1829,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3627,7 +3655,7 @@ xran_spawn_workers(void) +@@ -3627,7 +3681,7 @@ xran_spawn_workers(void) } /** 4 UP GEN **/ @@ -1704,7 +1838,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3642,7 +3670,7 @@ xran_spawn_workers(void) +@@ -3642,7 +3696,7 @@ xran_spawn_workers(void) eth_ctx->pkt_wrk_cfg[pThCtx->worker_id].arg = pThCtx; /** 5 UP GEN **/ @@ -1713,7 +1847,7 @@ index 7c472d7..7c7cf91 100644 if(pThCtx == NULL){ print_err("pThCtx allocation error\n"); return XRAN_STATUS_FAIL; -@@ -3754,6 +3782,7 @@ xran_open(void *pHandle, struct xran_fh_config* pConf) +@@ -3754,6 +3808,7 @@ xran_open(void *pHandle, struct xran_fh_config* pConf) p_xran_dev_ctx->puschMaskSlot = pConf->puschMaskSlot; p_xran_dev_ctx->DynamicSectionEna = pConf->DynamicSectionEna; p_xran_dev_ctx->RunSlotPrbMapBySymbolEnable = pConf->RunSlotPrbMapBySymbolEnable; @@ -1721,7 +1855,7 @@ index 7c472d7..7c7cf91 100644 p_xran_dev_ctx->dssEnable = pConf->dssEnable; p_xran_dev_ctx->dssPeriod = pConf->dssPeriod; for(i=0; idssPeriod; i++) { -@@ -4034,6 +4063,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, +@@ -4034,6 +4089,24 @@ xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, return tti; } @@ -1746,7 +1880,7 @@ index 7c472d7..7c7cf91 100644 int32_t xran_set_debug_stop(int32_t value, int32_t count) { -@@ -4208,7 +4255,7 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str +@@ -4208,7 +4281,7 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str int32_t i = 0, j = 0, nPrbElm = 0; int16_t iqwidth = p_PrbMapIn->prbMap[0].iqWidth; struct xran_prb_elm *p_prb_elm_src, *p_prb_elm_dst; @@ -1755,7 +1889,7 @@ index 7c472d7..7c7cf91 100644 int32_t nRBStart_tmp, nRBremain, nStartSymb, nEndSymb, nRBStart, nRBEnd, nRBSize; // int32_t eth_xran_up_headers_sz = sizeof(struct eth_xran_up_pkt_hdr); // int32_t nmaxRB = (mtu - eth_xran_up_headers_sz - RTE_PKTMBUF_HEADROOM)/XRAN_PAYLOAD_1_RB_SZ(iqwidth); -@@ -4217,7 +4264,6 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str +@@ -4217,7 +4290,6 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str if (mtu==9600) nmaxRB--; //for some reason when mtu is 9600, only 195 RB can be sent, not 196 @@ -1763,7 +1897,7 @@ index 7c472d7..7c7cf91 100644 memcpy(p_PrbMapOut, p_PrbMapIn, sizeof(struct xran_prb_map)); for(i = 0; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++) { -@@ -4292,26 +4338,30 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str +@@ -4292,26 +4364,30 @@ int32_t xran_init_PrbMap_by_symbol_from_cfg(struct xran_prb_map* p_PrbMapIn, str for(; i < XRAN_NUM_OF_SYMBOL_PER_SLOT; i++) { @@ -2045,7 +2179,7 @@ index 72249bc..6b30084 100644 #include diff --git a/fhi_lib/lib/src/xran_tx_proc.c b/fhi_lib/lib/src/xran_tx_proc.c -index 45a17a8..85ce6fa 100644 +index 45a17a8..cca2dcc 100644 --- a/fhi_lib/lib/src/xran_tx_proc.c +++ b/fhi_lib/lib/src/xran_tx_proc.c @@ -35,7 +35,11 @@ @@ -2060,7 +2194,19 @@ index 45a17a8..85ce6fa 100644 #include #include -@@ -1514,7 +1518,11 @@ xran_process_tx_sym_cp_on_opt(void* pHandle, uint8_t ctx_id, uint32_t tti, int32 +@@ -1399,6 +1403,11 @@ xran_process_tx_sym_cp_on_opt(void* pHandle, uint8_t ctx_id, uint32_t tti, int32 + + if(0!=ptr_sect_elm->cur_index) + { ++ /* prevent xran from sending DL U-plane packets when it should not */ ++ if(p_xran_dev_ctx->fh_init.io_cfg.id == O_DU && xran_fs_get_slot_type(xran_port_id, 0, tti, XRAN_SLOT_TYPE_DL) != 1) ++ { ++ return 0; ++ } + num_sections = ptr_sect_elm->cur_index; + /* iterate C-Plane configuration to generate corresponding U-Plane */ + vf_id = p_xran_dev_ctx->map2vf[direction][cc_id][ant_id][XRAN_UP_VF]; +@@ -1514,7 +1523,11 @@ xran_process_tx_sym_cp_on_opt(void* pHandle, uint8_t ctx_id, uint32_t tti, int32 mb_oran_hdr_ext->buf_addr = ext_buff; mb_oran_hdr_ext->buf_iova = ((struct rte_mempool_objhdr*)RTE_PTR_SUB(mb_base, rte_mempool_objhdr_size))->iova + RTE_PTR_DIFF(ext_buff, mb_base); mb_oran_hdr_ext->buf_len = ext_buff_len; @@ -2072,7 +2218,7 @@ index 45a17a8..85ce6fa 100644 mb_oran_hdr_ext->shinfo = p_share_data; mb_oran_hdr_ext->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM, (uint16_t)mb_oran_hdr_ext->buf_len) - rte_ether_hdr_size; mb_oran_hdr_ext->data_len = (uint16_t)(mb_oran_hdr_ext->data_len + rte_ether_hdr_size); -@@ -1532,8 +1540,13 @@ xran_process_tx_sym_cp_on_opt(void* pHandle, uint8_t ctx_id, uint32_t tti, int32 +@@ -1532,8 +1545,13 @@ xran_process_tx_sym_cp_on_opt(void* pHandle, uint8_t ctx_id, uint32_t tti, int32 /* Fill in the ethernet header. */ #ifndef TRANSMIT_BURST @@ -2086,7 +2232,7 @@ index 45a17a8..85ce6fa 100644 ((struct rte_ether_hdr*)pStart)->ether_type = ETHER_TYPE_ECPRI_BE; /* ethertype */ #endif nPktSize = sizeof(struct rte_ether_hdr) -@@ -1878,7 +1891,11 @@ xran_process_tx_srs_cp_on(void* pHandle, uint8_t ctx_id, uint32_t tti, int32_t s +@@ -1878,7 +1896,11 @@ xran_process_tx_srs_cp_on(void* pHandle, uint8_t ctx_id, uint32_t tti, int32_t s mb_oran_hdr_ext->buf_addr = ext_buff; mb_oran_hdr_ext->buf_iova = ((struct rte_mempool_objhdr*)RTE_PTR_SUB(mb_base, rte_mempool_objhdr_size))->iova + RTE_PTR_DIFF(ext_buff, mb_base); mb_oran_hdr_ext->buf_len = ext_buff_len; @@ -2098,7 +2244,7 @@ index 45a17a8..85ce6fa 100644 mb_oran_hdr_ext->shinfo = p_share_data; mb_oran_hdr_ext->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM, (uint16_t)mb_oran_hdr_ext->buf_len) - rte_ether_hdr_size; mb_oran_hdr_ext->data_len = (uint16_t)(mb_oran_hdr_ext->data_len + rte_ether_hdr_size); -@@ -1887,8 +1904,13 @@ xran_process_tx_srs_cp_on(void* pHandle, uint8_t ctx_id, uint32_t tti, int32_t s +@@ -1887,8 +1909,13 @@ xran_process_tx_srs_cp_on(void* pHandle, uint8_t ctx_id, uint32_t tti, int32_t s pStart = (char*)((char*)mb_oran_hdr_ext->buf_addr + mb_oran_hdr_ext->data_off); /* Fill in the ethernet header. */ diff --git a/radio/fhi_72/CMakeLists.txt b/radio/fhi_72/CMakeLists.txt index c0546aaca8..e7e87560f9 100644 --- a/radio/fhi_72/CMakeLists.txt +++ b/radio/fhi_72/CMakeLists.txt @@ -17,7 +17,7 @@ add_library(oran_fhlib_5g MODULE ) set(E_VERSION 5.1.6) -set(F_VERSION 6.1.7) +set(F_VERSION 6.1.8) find_package(xran REQUIRED) if(xran_VERSION VERSION_EQUAL E_VERSION) From 0388bf0e67d70b5fb96bb983d96bb3da2cd9f872 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Thu, 6 Nov 2025 06:16:43 +0000 Subject: [PATCH 03/17] protoru: add docs and sample config --- doc/ORAN_FHI7.2_Tutorial.md | 32 +- ...b.sa.band78.106prb.fhi72.1x1-proto-ru.conf | 278 ++++++++++++++++++ 2 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index e3bb8e44c1..ca10c768ce 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -719,7 +719,37 @@ RU must be rebooted so the changes apply. - The measured throughput was **520 Mbps DL** and **40 Mbps UL**. - With newer OAI versions, throughput degrades. This issue is currently under investigation. -### Configure Network Interfaces and DPDK VFs +### ProtO-RU + +[ProtO-RU](https://github.com/NUS-CIR/ProtO-RU) is a software implementation of an O-RAN 7.2 RU using a NI USRP. +Different from other COTS RUs, ProtO-RU requires a larger DU delay profile which is larger than the TTI interval. + +The OAI configuration file [`gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf`](../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf) corresponds to: + +- TDD pattern `DDDSU`, 2.5ms +- Bandwidth 40MHz +- MTU 9216 +- 1T1R + +#### RU configuration + +First, compile the RU as outlined in the [building ProtO-RU tutorial](https://github.com/NUS-CIR/ProtO-RU/tree/proto-ru?tab=readme-ov-file#building-proto-ru). +Then, ensure that both your DU and ProtO-RU host are PTP synchronized. + +Next, use the RU config, [protoru-OAI-B210-TDD-n78-40MHz-1x1-30kHz.yml](https://github.com/NUS-CIR/ProtO-RU/blob/proto-ru/proto-ru/conf-files/protoru-OAI-B210-TDD-n78-40MHz-1x1-30kHz.yml), which corresponds to the above mentioned DU config file. +In addition, please adapt the DU MAC address and VLAN tag to your needs. + +ProtO-RU was successfully tested with USRP B210. +If you are using a different SDR (e.g., N310), you will need to update the ProtO-RU and the DU configurations accordingly. + +Launch ProtO-RU with the adapted configuration file with the command: +```bash +sudo ./ru_emulator -c +``` + +Finally, start the OAI gNB. + +## Configure Network Interfaces and DPDK VFs The 7.2 fronthaul uses the xran library, which requires DPDK. In this step, we need to configure network interfaces to send data to the RU, and configure DPDK diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf new file mode 100644 index 0000000000..4027673ff3 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf @@ -0,0 +1,278 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe01; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ( { sst = 1; }); }); + + nr_cellid = 1; + # min_rxtxtime = 4; + ////////// Physical parameters: + + pdsch_AntennaPorts_XP = 1; + pusch_AntennaPorts = 1; + do_CSIRS = 0; + do_SRS = 0; + sib1_tda = 15; + force_256qam_off = 0; + force_UL256qam_off = 0; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + #n_TimingAdvanceOffset = 1; +# downlinkConfigCommon + #frequencyInfoDL + # center frequency = 3420.48MHz + # selected SSB frequency = 3349.92 MHz + absoluteFrequencySSB = 627456; + dl_frequencyBand = 78; + # frequency point A = 3401.40 MHz + dl_absoluteFrequencyPointA = 626760; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + initialDLBWPlocationAndBandwidth = 28875; #38.101-1 Table 5.3.2-1 + # +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 23; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 159; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 0; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 7; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 3; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 5; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1; +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0; + +# this is the offset between the last PRACH preamble power and the Msg3 PUSCH, 2 times the field value in dB + msg3_DeltaPreamble = 4; + p0_NominalWithGrant = -24; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 0; + p0_nominal = -24; + + ssb_PositionsInBurst_Bitmap = 0x1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 5; + nrofDownlinkSlots = 3; + nrofDownlinkSymbols = 10; + nrofUplinkSlots = 1; + nrofUplinkSymbols = 2; + + ssPBCH_BlockPower = 20; + } + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "172.22.0.10"; }); + + NETWORK_INTERFACES : + { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.26.190.95"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.26.190.95"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 250; + pucch_TargetSNRx10 = 200; + #dl_bler_target_upper = .35; + #dl_bler_target_lower = .15; + #ul_bler_target_upper = .35; + #ul_bler_target_lower = .15; + pusch_FailureThres = 1000; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 200; + pucch0_dtx_threshold = 100; + pusch_dtx_threshold = 10; + max_ldpc_iterations = 15; + tx_amp_backoff_dB = 9; # needs to match O-RU configuration + L1_rx_thread_core = 8; + L1_tx_thread_core = 10; + phase_compensation = 0; # needs to match O-RU configuration +} +); + +RUs = ( +{ + local_rf = "no"; + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 75; + sf_extension = 0; + eNB_instances = [0]; + ru_thread_core = 9; + sl_ahead = 10; + tr_preference = "raw_if4p5"; # important: activate FHI7.2 + do_precoding = 0; # needs to match O-RU configuration +} +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "no"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level = "info"; + hw_log_level = "info"; + phy_log_level = "info"; + mac_log_level = "info"; + nr_mac_log_level = "info"; + rlc_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + ngap_log_level = "info"; + f1ap_log_level = "info"; +}; + +fhi_72 = { + dpdk_devices = ("0000:70:11.0"); # one VF can be used as well + system_core = 0; + io_core = 1; + worker_cores = (2); + ru_addr = ("50:7c:6f:45:f3:04"); + mtu = 9600; + fh_config = ({ + T1a_cp_dl = (2450, 2635); + T1a_cp_ul = (2450, 2635); + T1a_up = (2350, 2550); + Ta4 = (1500, 1990); + ru_config = { + iq_width = 9; + iq_width_prach = 9; + }; + prach_config = { + eAxC_offset = 4; + }; + }); +}; + From 34c001d488cef8ee5beea0914efb40a92eb288f2 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Mon, 2 Feb 2026 15:07:42 +0000 Subject: [PATCH 04/17] protoru: sample config update --- .../gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf index 4027673ff3..0308d2aac7 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf @@ -21,7 +21,6 @@ gNBs = pusch_AntennaPorts = 1; do_CSIRS = 0; do_SRS = 0; - sib1_tda = 15; force_256qam_off = 0; force_UL256qam_off = 0; @@ -86,9 +85,6 @@ gNBs = #powerRampingStep # 0=dB0,1=dB2,2=dB4,3=dB6 powerRampingStep = 3; -#ra_ReponseWindow -#1,2,4,8,10,20,40,80 - ra_ResponseWindow = 5; #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; @@ -148,7 +144,7 @@ gNBs = nrofUplinkSlots = 1; nrofUplinkSymbols = 2; - ssPBCH_BlockPower = 20; + ssPBCH_BlockPower = 0; } ); @@ -260,11 +256,11 @@ fhi_72 = { io_core = 1; worker_cores = (2); ru_addr = ("50:7c:6f:45:f3:04"); - mtu = 9600; + mtu = 9216; fh_config = ({ - T1a_cp_dl = (2450, 2635); - T1a_cp_ul = (2450, 2635); - T1a_up = (2350, 2550); + T1a_cp_dl = (2566, 2585); + T1a_cp_ul = (2566, 2585); + T1a_up = (2200, 2300); Ta4 = (1500, 1990); ru_config = { iq_width = 9; From 95df8b174ec73fc59218dfae825f14102320f51a Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Mon, 2 Feb 2026 15:28:06 +0000 Subject: [PATCH 05/17] protoru: fix doc indent --- doc/ORAN_FHI7.2_Tutorial.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ORAN_FHI7.2_Tutorial.md b/doc/ORAN_FHI7.2_Tutorial.md index ca10c768ce..a241fbb3f5 100644 --- a/doc/ORAN_FHI7.2_Tutorial.md +++ b/doc/ORAN_FHI7.2_Tutorial.md @@ -719,7 +719,7 @@ RU must be rebooted so the changes apply. - The measured throughput was **520 Mbps DL** and **40 Mbps UL**. - With newer OAI versions, throughput degrades. This issue is currently under investigation. -### ProtO-RU +#### ProtO-RU [ProtO-RU](https://github.com/NUS-CIR/ProtO-RU) is a software implementation of an O-RAN 7.2 RU using a NI USRP. Different from other COTS RUs, ProtO-RU requires a larger DU delay profile which is larger than the TTI interval. @@ -731,7 +731,7 @@ The OAI configuration file [`gnb.sa.band78.106prb.fhi72.1x1-proto-ru.conf`](../t - MTU 9216 - 1T1R -#### RU configuration +##### RU configuration First, compile the RU as outlined in the [building ProtO-RU tutorial](https://github.com/NUS-CIR/ProtO-RU/tree/proto-ru?tab=readme-ov-file#building-proto-ru). Then, ensure that both your DU and ProtO-RU host are PTP synchronized. From 315fe922536480246908545a805247a4410fd04b Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Wed, 28 Jan 2026 08:39:38 +0100 Subject: [PATCH 06/17] Enable imscope for split7.2 --- executables/nr-softmodem.c | 27 ++++++++++++++------- openair1/PHY/TOOLS/imscope/imscope_init.cpp | 3 ++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 479aec465f..614fecad62 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -675,11 +675,28 @@ int main( int argc, char **argv ) { wait_nfapi_init("main?"); } + if (IS_SOFTMODEM_IMSCOPE_ENABLED || IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) { + sleep(1); + scopeParms_t p; + p.argc = &argc; + p.argv = argv; + p.gNB = RC.gNB[0]; + p.ru = RC.ru[0]; + if (IS_SOFTMODEM_IMSCOPE_ENABLED) { + load_softscope("im", &p); + } + AssertFatal(!(IS_SOFTMODEM_IMSCOPE_ENABLED && IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED), + "Data recoding and ImScope cannot be enabled at the same time\n"); + if (IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) { + load_module_shlib("imscope_record", NULL, 0, &p); + } + } + 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) - if (IS_SOFTMODEM_DOSCOPE || IS_SOFTMODEM_IMSCOPE_ENABLED || IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) { + if (IS_SOFTMODEM_DOSCOPE) { sleep(1); scopeParms_t p; p.argc = &argc; @@ -689,14 +706,6 @@ int main( int argc, char **argv ) { if (IS_SOFTMODEM_DOSCOPE) { load_softscope("nr", &p); } - if (IS_SOFTMODEM_IMSCOPE_ENABLED) { - load_softscope("im", &p); - } - AssertFatal(!(IS_SOFTMODEM_IMSCOPE_ENABLED && IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED), - "Data recoding and ImScope cannot be enabled at the same time\n"); - if (IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) { - load_module_shlib("imscope_record", NULL, 0, &p); - } } if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF && NFAPI_MODE != NFAPI_MODE_AERIAL) { diff --git a/openair1/PHY/TOOLS/imscope/imscope_init.cpp b/openair1/PHY/TOOLS/imscope/imscope_init.cpp index 2bb3d8dd33..ea0b26dea6 100644 --- a/openair1/PHY/TOOLS/imscope/imscope_init.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope_init.cpp @@ -41,7 +41,8 @@ extern "C" void imscope_autoinit(void *dataptr) if (IS_SOFTMODEM_GNB) { scopeParms_t *scope_params = (scopeParms_t *)dataptr; scope_params->gNB->scopeData = scope; - scope_params->ru->scopeData = scope; + if (scope_params->ru) + scope_params->ru->scopeData = scope; } else { PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)dataptr; ue->scopeData = scope; From aeba59a9adc2e35bc81284943217a54913acdb72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 30 Jan 2026 10:10:46 +0000 Subject: [PATCH 07/17] Change Aerial to pack directly in nvIPC message buffer. Get mempool sizes from nvIPC for usage in the packing procedures. Remove now unused functions. --- nfapi/oai_integration/aerial/fapi_nvIPC.c | 343 +++++---------------- nfapi/oai_integration/aerial/fapi_nvIPC.h | 13 +- nfapi/oai_integration/aerial/fapi_vnf_p7.c | 59 +++- 3 files changed, 129 insertions(+), 286 deletions(-) diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index 05c08d391d..bbb0d66900 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -63,6 +63,10 @@ char cpu_buf_recv[RECV_BUF_LEN]; uint16_t sfn = 0, slot = 0; nv_ipc_t *ipc; +static nv_ipc_config_t nv_ipc_config; +static int cpu_msg_buf_size = 0; +static int cpu_data_buf_size = 0; + void nvIPC_Stop() { LOG_I(NR_MAC, "Received STOP.indication\n"); @@ -95,7 +99,7 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) nfapi_vnf_config_t * vnf_config = get_config(); if (vnf_config != 0) { // first, unpack the header - fapi_phy_api_msg fapi_msg; + fapi_message_header_t fapi_msg; if (!(pull8(&pReadPackedMessage, &fapi_msg.num_msg, end) && pull8(&pReadPackedMessage, &fapi_msg.opaque_handle, end) && pull16(&pReadPackedMessage, &fapi_msg.message_id, end) && pull32(&pReadPackedMessage, &fapi_msg.message_length, end))) { @@ -195,267 +199,78 @@ static int ipc_handle_rx_msg(nv_ipc_t *ipc, nv_ipc_msg_t *msg) return 0; } -int8_t buf[1024]; +int get_cpu_msg_buf_size() +{ + return cpu_msg_buf_size; +} +int get_cpu_data_buf_size() +{ + return cpu_data_buf_size; +} -nv_ipc_config_t nv_ipc_config; +bool allocate_msg(nv_ipc_msg_t *send_msg) +{ + return ipc->tx_allocate(ipc, send_msg, 0) == 0; +} +void release_msg(nv_ipc_msg_t *send_msg) +{ + ipc->tx_release(ipc, send_msg); +} + +bool send_nvipc_msg(nv_ipc_msg_t *send_msg) +{ + int send_retval = ipc->tx_send_msg(ipc, send_msg); + if (send_retval != 0) { + LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); + ipc->tx_release(ipc, send_msg); + return false; + } + + ipc->notify(ipc, 1); // notify that there's 1 message in queue + return true; +} bool aerial_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) { nfapi_vnf_pnf_info_t *pnf = nfapi_vnf_pnf_list_find(&(vnf->_public), p5_idx); if (pnf) { - uint8_t tx_messagebufferFAPI[sizeof(vnf->tx_message_buffer)]; + // Create the message + nv_ipc_msg_t send_msg = {.msg_id = msg->message_id, + .cell_id = 0, + // For P5 we don't need CPU_DATA + .data_pool = NV_IPC_MEMPOOL_CPU_MSG, + .data_len = 0, + .data_buf = NULL}; + + // Allocate the message + if (!allocate_msg(&send_msg)) { + return false; + } + int packedMessageLengthFAPI = -1; - packedMessageLengthFAPI = - vnf->_public.pack_func(msg, msg_len, tx_messagebufferFAPI, sizeof(tx_messagebufferFAPI), &vnf->_public.codec_config); - return aerial_send_P5_msg(tx_messagebufferFAPI, packedMessageLengthFAPI, msg) == 0; + // Pack directly into it + if ((packedMessageLengthFAPI = + vnf->_public.pack_func(msg, msg_len, send_msg.msg_buf, get_cpu_msg_buf_size(), &vnf->_public.codec_config)) + < 0) { + release_msg(&send_msg); + return false; + } + if (packedMessageLengthFAPI <= 0) { + LOG_E(NFAPI_VNF, "Error packing message 0x%02x\n", msg->message_id); + release_msg(&send_msg); + return false; + } + // Set the length + send_msg.msg_len = packedMessageLengthFAPI + 8; // adding 8 to account for the size of the FAPI header + // Send + return send_nvipc_msg(&send_msg); } else { NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() cannot find pnf info for p5_idx:%d\n", __FUNCTION__, p5_idx); return false; } } -bool aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header) -{ - if (ipc == NULL) { - return false; - } - nv_ipc_msg_t send_msg = {0}; - // look for the specific message - switch (header->message_id) { - case NFAPI_NR_PHY_MSG_TYPE_PARAM_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE: - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE: - case NFAPI_NR_PHY_MSG_TYPE_START_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_START_RESPONSE: - case NFAPI_NR_PHY_MSG_TYPE_STOP_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_STOP_RESPONSE: - break; - default: { - if (header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { - // if(config && config->pack_p4_p5_vendor_extension) { - // result = (config->pack_p4_p5_vendor_extension)(header, ppWritePackedMsg, end, config); - // } else { - // NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s VE NFAPI message ID %d. No ve ecoder provided\n", __FUNCTION__, header->message_id); - // } - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); - } - } break; - } - send_msg.msg_id = header->message_id; - send_msg.cell_id = 0; - send_msg.msg_len = packedMsgLength + 8; // adding 8 to account for the size of the FAPI header - send_msg.data_len = 0; - send_msg.data_buf = NULL; - send_msg.data_pool = NV_IPC_MEMPOOL_CPU_MSG; - - // procedure is allocate->fill->send - int alloc_retval = ipc->tx_allocate(ipc, &send_msg, 0); - if (alloc_retval != 0) { - LOG_E(NFAPI_VNF, "%s error: allocate TX buffer failed Error: %d\n", __FUNCTION__, alloc_retval); - ipc->tx_release(ipc, &send_msg); - return false; - } - - memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); - LOG_D(NFAPI_VNF, - "send: cell_id=%d msg_id=0x%02X msg_len=%d data_len=%d data_pool=%d\n", - send_msg.cell_id, - send_msg.msg_id, - send_msg.msg_len, - send_msg.data_len, - send_msg.data_pool); - // Send the message - int send_retval = ipc->tx_send_msg(ipc, &send_msg); - if (send_retval < 0) { - LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); - ipc->tx_release(ipc, &send_msg); - return false; - } - - ipc->notify(ipc, 1); // notify that there's 1 message in queue - return true; -} - -bool aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header) -{ - if (ipc == NULL) { - return false; - } - nv_ipc_msg_t send_msg; - uint8_t *pPacketBodyField = &((uint8_t *)packedBuf)[8]; - uint8_t *pPackMessageEnd = packedBuf + packedMsgLength + 8; - - uint16_t present_sfn = 0; - uint16_t present_slot = 0; - pull16(&pPacketBodyField, &present_sfn, pPackMessageEnd); - pull16(&pPacketBodyField, &present_slot, pPackMessageEnd); - - if (present_sfn != old_sfn || present_slot != old_slot) { - LOG_E(NFAPI_VNF, - "\n============================================================================\n" - "sfn slot doesn't match unpacked one! L2->L1 %d.%d vs L1->L2 %d.%d \n" - "============================================================================\n", - present_sfn, - present_slot, - old_sfn, - old_slot); - } - // look for the specific message - switch (header->message_id) { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - case NFAPI_UE_RELEASE_REQUEST: - case NFAPI_UE_RELEASE_RESPONSE: - case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - case NFAPI_TIMING_INFO: - case 0x8f: - break; - default: { - if (header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); - } - } break; - } - - send_msg.msg_id = header->message_id; - send_msg.cell_id = 0; - send_msg.msg_len = packedMsgLength + 8; // adding 8 to account for the size of the FAPI header - send_msg.data_len = 0; - send_msg.data_buf = NULL; - send_msg.data_pool = NV_IPC_MEMPOOL_CPU_MSG; - // procedure is allocate->fill->send - - // Allocate buffer for TX message - int alloc_retval = ipc->tx_allocate(ipc, &send_msg, 0); - if (alloc_retval != 0) { - LOG_E(NFAPI_VNF, "%s error: allocate TX buffer failed Error: %d\n", __FUNCTION__, alloc_retval); - ipc->tx_release(ipc, &send_msg); - return false; - } - - memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); - LOG_D(NFAPI_VNF, - "send: cell_id=%d msg_id=0x%02X msg_len=%d data_len=%d data_pool=%d\n", - send_msg.cell_id, - send_msg.msg_id, - send_msg.msg_len, - send_msg.data_len, - send_msg.data_pool); - // Send the message - int send_retval = ipc->tx_send_msg(ipc, &send_msg); - if (send_retval < 0) { - LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); - ipc->tx_release(ipc, &send_msg); - return false; - } - - ipc->notify(ipc, 1); // notify that there's 1 message in queue - return true; -} - -bool aerial_send_P7_msg_with_data(void *packedBuf, - uint32_t packedMsgLength, - void *dataBuf, - uint32_t dataLength, - nfapi_nr_p7_message_header_t *header) -{ - if (ipc == NULL) { - return false; - } - nv_ipc_msg_t send_msg; - uint8_t *pPacketBodyField = &((uint8_t *)packedBuf)[8]; - uint8_t *pPackMessageEnd = packedBuf + packedMsgLength + 8; - uint16_t present_sfn = 0; - uint16_t present_slot = 0; - pull16(&pPacketBodyField, &present_sfn, pPackMessageEnd); - pull16(&pPacketBodyField, &present_slot, pPackMessageEnd); - - if (present_sfn != old_sfn || present_slot != old_slot) { - LOG_E(NFAPI_VNF, - "\n============================================================================\n" - "sfn slot doesn't match unpacked one! L2->L1 %d.%d vs L1->L2 %d.%d \n" - "============================================================================\n", - present_sfn, - present_slot, - old_sfn, - old_slot); - } - // look for the specific message - switch (header->message_id) { - case NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST: - case NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST: - case NFAPI_UE_RELEASE_REQUEST: - case NFAPI_UE_RELEASE_RESPONSE: - case NFAPI_NR_PHY_MSG_TYPE_SLOT_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION: - case NFAPI_NR_PHY_MSG_TYPE_DL_NODE_SYNC: - case NFAPI_NR_PHY_MSG_TYPE_UL_NODE_SYNC: - case NFAPI_TIMING_INFO: - break; - default: { - if (header->message_id >= NFAPI_VENDOR_EXT_MSG_MIN && header->message_id <= NFAPI_VENDOR_EXT_MSG_MAX) { - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s NFAPI Unknown message ID %d\n", __FUNCTION__, header->message_id); - } - } break; - } - - send_msg.msg_id = header->message_id; - send_msg.cell_id = 0; - send_msg.msg_len = packedMsgLength + 8; // adding 8 to account for the size of the FAPI header - send_msg.data_len = dataLength; - send_msg.data_pool = NV_IPC_MEMPOOL_CPU_DATA; - - // procedure is allocate->fill->send - - // Allocate buffer for TX message - int alloc_retval = ipc->tx_allocate(ipc, &send_msg, 0); - if (alloc_retval != 0) { - LOG_E(NFAPI_VNF, "%s error: allocate TX buffer failed Error: %d\n", __FUNCTION__, alloc_retval); - ipc->tx_release(ipc, &send_msg); - return false; - } - - memcpy(send_msg.msg_buf, packedBuf, send_msg.msg_len); - memcpy(send_msg.data_buf, dataBuf, send_msg.data_len); - LOG_D(NFAPI_VNF, - "send: cell_id=%d msg_id=0x%02X msg_len=%d data_len=%d data_pool=%d\n", - send_msg.cell_id, - send_msg.msg_id, - send_msg.msg_len, - send_msg.data_len, - send_msg.data_pool); - // Send the message - int send_retval = ipc->tx_send_msg(ipc, &send_msg); - if (send_retval != 0) { - LOG_E(NFAPI_VNF, "%s error: send TX message failed Error: %d\n", __FUNCTION__, send_retval); - ipc->tx_release(ipc, &send_msg); - return false; - } - - ipc->notify(ipc, 1); // notify that there's 1 message in queue - return true; -} - // Always allocate message buffer, but allocate data buffer only when data_len > 0 static int aerial_recv_msg(nv_ipc_t *ipc, nv_ipc_msg_t *recv_msg) { @@ -568,6 +383,10 @@ int nvIPC_Init(nvipc_params_t nvipc_params_s) { // Want to use transport SHM, type epoll, module secondary (reads the created shm from cuphycontroller) load_hard_code_config(&nv_ipc_config, NV_IPC_MODULE_SECONDARY, NV_IPC_TRANSPORT_SHM); + // save the mempool sizes for later use in packing + cpu_msg_buf_size = nv_ipc_get_buf_size(&nv_ipc_config, NV_IPC_MEMPOOL_CPU_MSG); + cpu_data_buf_size = nv_ipc_get_buf_size(&nv_ipc_config, NV_IPC_MEMPOOL_CPU_DATA); + // Create nv_ipc_t instance LOG_I(NFAPI_VNF, "%s: creating IPC interface with prefix %s\n", __func__, nvipc_params_s.nvipc_shm_prefix); strcpy(nv_ipc_config.transport_config.shm.prefix, nvipc_params_s.nvipc_shm_prefix); @@ -588,10 +407,9 @@ int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST; - // int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req); - int retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_tti_req->header); + bool retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_tti_req->header); - if (retval != 0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { // Reset number of PDUs so that it is not resent @@ -608,9 +426,9 @@ int oai_fapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST; - // int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req); - int retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_dci_req->header); - if (retval != 0) { + + bool retval = p7_config->send_p7_msg(get_p7_vnf(), &ul_dci_req->header); + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { ul_dci_req->numPdus = 0; @@ -623,10 +441,9 @@ int oai_fapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req) nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST; - // LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_data_req->SFN), - // tx_data_req->Number_of_PDUs); int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req); - int retval = p7_config->send_p7_msg(get_p7_vnf(), &tx_data_req->header); - if (retval != 0) { + + bool retval = p7_config->send_p7_msg(get_p7_vnf(), &tx_data_req->header); + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } else { tx_data_req->Number_of_PDUs = 0; @@ -640,11 +457,12 @@ int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); dl_config_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST; dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!! - int retval = p7_config->send_p7_msg(get_p7_vnf(), &dl_config_req->header); + + bool retval = p7_config->send_p7_msg(get_p7_vnf(), &dl_config_req->header); dl_config_req->dl_tti_request_body.nPDUs = 0; dl_config_req->dl_tti_request_body.nGroup = 0; - if (retval != 0) { + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } return retval; @@ -653,8 +471,9 @@ int oai_fapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req) int oai_fapi_send_end_request(int cell, uint32_t frame, uint32_t slot){ nfapi_vnf_p7_config_t *p7_config = get_p7_vnf_config(); nfapi_nr_slot_indication_scf_t nr_slot_resp = {.header.message_id = 0x8F, .sfn = frame, .slot = slot}; - int retval = p7_config->send_p7_msg(get_p7_vnf(), &nr_slot_resp.header); - if (retval != 0) { + + bool retval = p7_config->send_p7_msg(get_p7_vnf(), &nr_slot_resp.header); + if (!retval) { LOG_E(PHY, "%s() Problem sending retval:%d\n", __FUNCTION__, retval); } return retval; diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index 8740c1ecd3..f200bf36a7 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -48,15 +48,12 @@ typedef struct { uint32_t message_length; } fapi_phy_api_msg; +int get_cpu_msg_buf_size(); +int get_cpu_data_buf_size(); +bool allocate_msg(nv_ipc_msg_t* send_msg); +void release_msg(nv_ipc_msg_t* send_msg); +bool send_nvipc_msg(nv_ipc_msg_t* send_msg); bool aerial_nr_send_p5_message(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len); -bool aerial_send_P5_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p4_p5_message_header_t *header); -bool aerial_send_P7_msg(void *packedBuf, uint32_t packedMsgLength, nfapi_nr_p7_message_header_t *header); -bool aerial_send_P7_msg_with_data(void *packedBuf, - uint32_t packedMsgLength, - void *dataBuf, - uint32_t dataLength, - nfapi_nr_p7_message_header_t *header); - int nvIPC_Init(nvipc_params_t nvipc_params_s); int oai_fapi_send_end_request(int cell_id, uint32_t frame, uint32_t slot); int oai_fapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.c b/nfapi/oai_integration/aerial/fapi_vnf_p7.c index d9e3e0027b..927a61a761 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p7.c +++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.c @@ -180,40 +180,67 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, return (int32_t)(pMessageHeader->message_length); } - bool aerial_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *header) { - uint8_t FAPI_buffer[1024 * 64]; + // Common to both cases, we can set it now + // In most cases we don't need the data pool, only the CPU_MSG + nv_ipc_msg_t send_msg = {.msg_id = header->message_id, .data_pool = NV_IPC_MEMPOOL_CPU_MSG, .cell_id = 0}; // Check if TX_DATA request, if true, need to pack to data_buf if (header->message_id == NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST) { + // for this we need the secondary CPU_DATA pool + send_msg.data_pool = NV_IPC_MEMPOOL_CPU_DATA; + // Allocate the message after setting the data pool + if (!allocate_msg(&send_msg)) { + LOG_E(NFAPI_VNF, "Error in allocating nvipc message\n"); + return false; + } + nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)header; uint64_t size = 0; for (int i = 0; i < pNfapiMsg->Number_of_PDUs; ++i) { size += pNfapiMsg->pdu_list[i].PDU_length; } - AssertFatal(size <= 1024 * 1024 * 2, "Message data larger than available buffer, tried to pack %" PRId64, size); - uint8_t FAPI_data_buffer[1024 * 1024 * 2]; // 2MB + AssertFatal(size <= get_cpu_data_buf_size(), "Message data larger than available buffer, tried to pack %" PRId64, size); uint32_t data_len = 0; int32_t len_FAPI = aerial_pack_tx_data_request(header, - FAPI_buffer, - FAPI_data_buffer, - sizeof(FAPI_buffer), - sizeof(FAPI_data_buffer), + send_msg.msg_buf, + send_msg.data_buf, + get_cpu_msg_buf_size(), + get_cpu_data_buf_size(), &vnf_p7->_public.codec_config, ((nfapi_vnf_p7_config_t *)vnf_p7), &data_len); + + // Set both lengths + send_msg.msg_len = len_FAPI + 8; // adding 8 to account for the size of the FAPI header + send_msg.data_len = (int32_t)data_len; + if (len_FAPI <= 0) { LOG_E(NFAPI_VNF, "Problem packing TX_DATA_request\n"); + release_msg(&send_msg); return false; - } else { - return aerial_send_P7_msg_with_data(FAPI_buffer, len_FAPI, FAPI_data_buffer, data_len, header) == 0; } + // Send + return send_nvipc_msg(&send_msg); } else { - // Create and send FAPI P7 message - int len_FAPI = ((nfapi_vnf_p7_config_t *)vnf_p7)->pack_func(header, - FAPI_buffer, - sizeof(FAPI_buffer), - &vnf_p7->_public.codec_config); - return aerial_send_P7_msg(FAPI_buffer, len_FAPI, header) == 0; + send_msg.data_len = 0; + send_msg.data_buf = NULL; + // Allocate the message + if (!allocate_msg(&send_msg)) { + LOG_E(NFAPI_VNF, "Error in allocating nvipc message\n"); + return false; + } + // Pack directly into it + nfapi_vnf_p7_config_t* p7_config = (nfapi_vnf_p7_config_t *)vnf_p7; + int len_FAPI = p7_config->pack_func(header, send_msg.msg_buf, get_cpu_msg_buf_size(), &vnf_p7->_public.codec_config); + if (len_FAPI <= 0) { + LOG_E(NFAPI_VNF, "Problem packing message 0x%02x\n", header->message_id); + release_msg(&send_msg); + return false; + } + // Set the length + send_msg.msg_len = len_FAPI + 8; // adding 8 to account for the size of the FAPI header + // Send + return send_nvipc_msg(&send_msg); } } From 54076927ba89f74a3db3316e260539a7521ae433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Fri, 30 Jan 2026 10:26:12 +0000 Subject: [PATCH 08/17] Remove duplicated FAPI header struct from fapi_nvIPC.h --- nfapi/oai_integration/aerial/fapi_nvIPC.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.h b/nfapi/oai_integration/aerial/fapi_nvIPC.h index f200bf36a7..90a57f57eb 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.h +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.h @@ -41,13 +41,6 @@ #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" -typedef struct { - uint8_t num_msg; - uint8_t opaque_handle; - uint16_t message_id; - uint32_t message_length; -} fapi_phy_api_msg; - int get_cpu_msg_buf_size(); int get_cpu_data_buf_size(); bool allocate_msg(nv_ipc_msg_t* send_msg); From b7867a4053a5144d67b36a23ed663ae8134536a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAben=20Soares=20Silva?= Date: Tue, 3 Feb 2026 10:15:54 +0000 Subject: [PATCH 09/17] Change data_len type in aerial_pack_tx_data_request to match with nv_ipc_msg_t.data_len type --- nfapi/oai_integration/aerial/fapi_vnf_p7.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nfapi/oai_integration/aerial/fapi_vnf_p7.c b/nfapi/oai_integration/aerial/fapi_vnf_p7.c index 927a61a761..d9c331aea1 100644 --- a/nfapi/oai_integration/aerial/fapi_vnf_p7.c +++ b/nfapi/oai_integration/aerial/fapi_vnf_p7.c @@ -114,10 +114,10 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, void *pPackedBuf, void *pDataBuf, uint32_t packedBufLen, - uint32_t dataBufLen, + int32_t dataBufLen, nfapi_p7_codec_config_t *config, nfapi_vnf_p7_config_t *p7_config, - uint32_t *data_len) + int32_t *data_len) { if (pMessageBuf == NULL || pPackedBuf == NULL) { NFAPI_TRACE(NFAPI_TRACE_ERROR, "P7 Pack supplied pointers are null\n"); @@ -130,7 +130,7 @@ static int32_t aerial_pack_tx_data_request(void *pMessageBuf, uint8_t *pPackedDataField = &pDataPackedMessage[0]; uint8_t *pPackedDataFieldStart = &pDataPackedMessage[0]; uint8_t **ppWriteData = &pPackedDataField; - const uint32_t dataBufLen32 = (dataBufLen + 3) / 4; + const int32_t dataBufLen32 = (dataBufLen + 3) / 4; nfapi_nr_tx_data_request_t *pNfapiMsg = (nfapi_nr_tx_data_request_t *)pMessageHeader; // Actual payloads are packed in a separate buffer for (int i = 0; i < pNfapiMsg->Number_of_PDUs; i++) { @@ -201,7 +201,7 @@ bool aerial_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *h size += pNfapiMsg->pdu_list[i].PDU_length; } AssertFatal(size <= get_cpu_data_buf_size(), "Message data larger than available buffer, tried to pack %" PRId64, size); - uint32_t data_len = 0; + int32_t data_len = 0; int32_t len_FAPI = aerial_pack_tx_data_request(header, send_msg.msg_buf, send_msg.data_buf, @@ -213,7 +213,7 @@ bool aerial_nr_send_p7_message(vnf_p7_t *vnf_p7, nfapi_nr_p7_message_header_t *h // Set both lengths send_msg.msg_len = len_FAPI + 8; // adding 8 to account for the size of the FAPI header - send_msg.data_len = (int32_t)data_len; + send_msg.data_len = data_len; if (len_FAPI <= 0) { LOG_E(NFAPI_VNF, "Problem packing TX_DATA_request\n"); From df7db3ab278127aabe9e5d5a894ac083a1c462da Mon Sep 17 00:00:00 2001 From: Shubhika Garg Date: Wed, 4 Feb 2026 11:15:18 +0100 Subject: [PATCH 10/17] ci-fix: Ensure downstream pipeline always uses latest commit for non-MR events - ensure the local branch is synchronized with the latest commit from the remote. - Related MR!77 on mosaic5g/Flexric repository --- ci-scripts/Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/ci-scripts/Jenkinsfile b/ci-scripts/Jenkinsfile index abb2e3942c..3112b8f2cf 100644 --- a/ci-scripts/Jenkinsfile +++ b/ci-scripts/Jenkinsfile @@ -115,6 +115,7 @@ pipeline { } else { sh "git fetch" sh "git checkout -f ${commitID}" + sh "git reset --hard origin/${commitID}" } } else { echo "\u274C Some parameters are missing" From b533127553bd395168b20eb8d7ed412d9b7d6eef Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 15 Jan 2026 16:11:06 +0100 Subject: [PATCH 11/17] Ensure noise power is non-zero Prior to this commit, noise power estimation could be zero because of a call to clearArray() in gNB_I0_measurements(). This is problematic, as this can lead to a noise power of 0 if all symbols in a RB are used, which in turn leads to a spike in SNR. To avoid this, use an intermediate array to store noise power, and only update n0_subband_power if not all RBs are used (i.e., we can detect noise power). Further, use an exponential moving average to smoothen noise estimation. Fixes: fb4235fd50e9 ("changes in PUCCH0 SNR measurement, testing for PUCCH power control") --- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 89aba954e9..a14e903a3e 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -144,19 +144,8 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy PHY_MEASUREMENTS_gNB *measurements = &gNB->measurements; int nb_symb[275]={0}; - allocCast2D(n0_subband_power, - unsigned int, - gNB->measurements.n0_subband_power, - frame_parms->nb_antennas_rx, - frame_parms->N_RB_UL, - false); - clearArray(gNB->measurements.n0_subband_power, unsigned int); - allocCast2D(n0_subband_power_dB, - unsigned int, - gNB->measurements.n0_subband_power_dB, - frame_parms->nb_antennas_rx, - frame_parms->N_RB_UL, - false); + unsigned int tmp_n0_subband[frame_parms->nb_antennas_rx][frame_parms->N_RB_UL]; + memset(tmp_n0_subband, 0, sizeof(tmp_n0_subband)); // TODO modify the measurements to take into account concurrent beams for (int s = first_symb; s < first_symb + num_symb; s++) { @@ -176,7 +165,8 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy } else { signal_energy = signal_energy_nodc(ul_ch, 12); } - n0_subband_power[aarx][rb] += signal_energy; + // noise power per antenna/RB, symbols summed up + tmp_n0_subband[aarx][rb] += signal_energy; LOG_D(NR_PHY,"slot %d symbol %d RB %d aarx %d n0_subband_power %d\n", slot, s, rb, aarx, signal_energy); } //antenna } @@ -185,14 +175,28 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy int nb_rb=0; int64_t n0_subband_tot=0; int32_t n0_subband_tot_perANT[frame_parms->nb_antennas_rx]; - memset(n0_subband_tot_perANT, 0, sizeof(n0_subband_tot_perANT)); + allocCast2D(n0_subband_power, + unsigned int, + gNB->measurements.n0_subband_power, + frame_parms->nb_antennas_rx, + frame_parms->N_RB_UL, + false); + allocCast2D(n0_subband_power_dB, + unsigned int, + gNB->measurements.n0_subband_power_dB, + frame_parms->nb_antennas_rx, + frame_parms->N_RB_UL, + false); + for (int rb = 0 ; rbN_RB_UL;rb++) { int32_t n0_subband_tot_perPRB=0; if (nb_symb[rb] > 0) { for (int aarx=0;aarxnb_antennas_rx;aarx++) { - n0_subband_power[aarx][rb] /= nb_symb[rb]; + tmp_n0_subband[aarx][rb] /= nb_symb[rb]; + // apply exponential moving average to smooth noise measurements + n0_subband_power[aarx][rb] = 0.9 * n0_subband_power[aarx][rb] + 0.1 * tmp_n0_subband[aarx][rb]; n0_subband_power_dB[aarx][rb] = dB_fixed(n0_subband_power[aarx][rb]); n0_subband_tot_perPRB += n0_subband_power[aarx][rb]; n0_subband_tot_perANT[aarx] += n0_subband_power[aarx][rb]; From 656b1d52a008013cb28b6182836e9a0e62b7fc22 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 4 Feb 2026 19:04:00 +0100 Subject: [PATCH 12/17] Remove unused global variables --- openair1/PHY/INIT/nr_init.c | 1 - openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c | 14 +++----------- openair1/PHY/defs_gNB.h | 4 ---- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index ad92ae6c34..1615fc86f3 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -228,7 +228,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) PHY_MEASUREMENTS_gNB *meas = &gNB->measurements; free_and_zero(meas->n0_subband_power); - free_and_zero(meas->n0_subband_power_dB); for (int id = 0; id < gNB->max_nb_srs; id++) { for(int i=0; imeasurements.n0_subband_power, - frame_parms->nb_antennas_rx, - frame_parms->N_RB_UL, - false); - allocCast2D(n0_subband_power_dB, - unsigned int, - gNB->measurements.n0_subband_power_dB, + measurements->n0_subband_power, frame_parms->nb_antennas_rx, frame_parms->N_RB_UL, false); @@ -193,17 +187,15 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy for (int rb = 0 ; rbN_RB_UL;rb++) { int32_t n0_subband_tot_perPRB=0; if (nb_symb[rb] > 0) { - for (int aarx=0;aarxnb_antennas_rx;aarx++) { + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { tmp_n0_subband[aarx][rb] /= nb_symb[rb]; // apply exponential moving average to smooth noise measurements n0_subband_power[aarx][rb] = 0.9 * n0_subband_power[aarx][rb] + 0.1 * tmp_n0_subband[aarx][rb]; - n0_subband_power_dB[aarx][rb] = dB_fixed(n0_subband_power[aarx][rb]); n0_subband_tot_perPRB += n0_subband_power[aarx][rb]; n0_subband_tot_perANT[aarx] += n0_subband_power[aarx][rb]; } - n0_subband_tot_perPRB/=frame_parms->nb_antennas_rx; + n0_subband_tot_perPRB /= frame_parms->nb_antennas_rx; measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_subband_tot_perPRB); - measurements->n0_subband_power_tot_dBm[rb] = measurements->n0_subband_power_tot_dB[rb] - gNB->rx_total_gain_dB - dB_fixed(frame_parms->N_RB_UL); LOG_D(NR_PHY,"n0_subband_power_tot_dB[%d] => %d, over %d symbols\n",rb,measurements->n0_subband_power_tot_dB[rb],nb_symb[rb]); n0_subband_tot += n0_subband_tot_perPRB; nb_rb++; diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 46ba246dbe..62860283d9 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -340,16 +340,12 @@ typedef struct { unsigned int n0_power_tot_dB; //! estimated avg noise power per RB per RX ant (lin) fourDimArray_t *n0_subband_power; - //! estimated avg noise power per RB per RX ant (dB) - fourDimArray_t *n0_subband_power_dB; //! estimated avg subband noise power (dB) unsigned int n0_subband_power_avg_dB; //! estimated avg subband noise power per antenna (dB) unsigned int n0_subband_power_avg_perANT_dB[MAX_ANT]; //! estimated avg noise power per RB (dB) int n0_subband_power_tot_dB[275]; - //! estimated avg noise power per RB (dBm) - int n0_subband_power_tot_dBm[275]; /// PRACH background noise level int prach_I0; } PHY_MEASUREMENTS_gNB; From ee00eb346e1b761a166baa21c23e51083a65145a Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 4 Feb 2026 19:11:10 +0100 Subject: [PATCH 13/17] Reformat dump_nr_I0_stats() --- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 65 +++++++++++-------- openair1/PHY/NR_TRANSPORT/nr_ulsch.h | 2 - 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index fc190c4542..6005c39343 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -105,36 +105,47 @@ void nr_est_srs_timing_advance_offset(uint16_t ofdm_symbol_size, max_idx); } -void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB) { - - - int min_I0=1000,max_I0=0; - int amin=0,amax=0; - fprintf(fd,"Blacklisted PRBs %d/%d\n",gNB->num_ulprbbl,gNB->frame_parms.N_RB_UL); - for (int i=0; iframe_parms.N_RB_UL; i++) { - if (gNB->ulprbbl[i] > 0) continue; - - if (gNB->measurements.n0_subband_power_tot_dB[i]measurements.n0_subband_power_tot_dB[i]; amin=i;} - - if (gNB->measurements.n0_subband_power_tot_dB[i]>max_I0) {max_I0 = gNB->measurements.n0_subband_power_tot_dB[i]; amax=i;} +void dump_nr_I0_stats(FILE *fd, PHY_VARS_gNB *gNB) +{ + int min_I0 = 1000, max_I0 = 0; + int amin = 0, amax = 0; + fprintf(fd, "Blacklisted PRBs %d/%d\n", gNB->num_ulprbbl, gNB->frame_parms.N_RB_UL); + for (int i = 0; i < gNB->frame_parms.N_RB_UL; i++) { + if (gNB->ulprbbl[i] > 0) + continue; + if (gNB->measurements.n0_subband_power_tot_dB[i] < min_I0) { + min_I0 = gNB->measurements.n0_subband_power_tot_dB[i]; + amin = i; } - - for (int i=0; iframe_parms.N_RB_UL; i++) { - if (gNB->ulprbbl[i] ==0) fprintf(fd,"%2d.",gNB->measurements.n0_subband_power_tot_dB[i]-gNB->measurements.n0_subband_power_avg_dB); - else fprintf(fd," X."); - if (i%25 == 24) fprintf(fd,"\n"); + if (gNB->measurements.n0_subband_power_tot_dB[i] > max_I0) { + max_I0 = gNB->measurements.n0_subband_power_tot_dB[i]; + amax = i; } - fprintf(fd,"\n"); - fprintf(fd,"max_IO = %d (%d), min_I0 = %d (%d), avg_I0 = %d dB",max_I0,amax,min_I0,amin,gNB->measurements.n0_subband_power_avg_dB); - if (gNB->frame_parms.nb_antennas_rx>1) { - fprintf(fd,"("); - for (int aarx=0;aarxframe_parms.nb_antennas_rx;aarx++) - fprintf(fd,"%d.",gNB->measurements.n0_subband_power_avg_perANT_dB[aarx]); - fprintf(fd,")"); - } - fprintf(fd,"\nPRACH I0 = %d.%d dB\n",gNB->measurements.prach_I0/10,gNB->measurements.prach_I0%10); - + } + for (int i = 0; i < gNB->frame_parms.N_RB_UL; i++) { + if (gNB->ulprbbl[i] == 0) + fprintf(fd, "%2d.", gNB->measurements.n0_subband_power_tot_dB[i] - gNB->measurements.n0_subband_power_avg_dB); + else + fprintf(fd, " X."); + if (i % 25 == 24) + fprintf(fd, "\n"); + } + fprintf(fd, "\n"); + fprintf(fd, + "max_IO = %d (%d), min_I0 = %d (%d), avg_I0 = %d dB", + max_I0, + amax, + min_I0, + amin, + gNB->measurements.n0_subband_power_avg_dB); + if (gNB->frame_parms.nb_antennas_rx > 1) { + fprintf(fd, "("); + for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx++) + fprintf(fd, "%d.", gNB->measurements.n0_subband_power_avg_perANT_dB[aarx]); + fprintf(fd, ")"); + } + fprintf(fd, "\nPRACH I0 = %d.%d dB\n", gNB->measurements.prach_I0 / 10, gNB->measurements.prach_I0 % 10); } void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_symb, uint32_t rb_mask_ul[14][9]) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index 95474f64c0..0f66e49ff6 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -74,8 +74,6 @@ void nr_ulsch_layer_demapping(int16_t *llr_cw, uint8_t Nl, uint8_t mod_order, ui void dump_pusch_stats(FILE *fd,PHY_VARS_gNB *gNB); -void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); - NR_gNB_SCH_STATS_t *get_ulsch_stats(PHY_VARS_gNB *gNB,NR_gNB_ULSCH_t *ulsch); #endif /* NR_ULSCH_H_ */ From 74b998a0d8c8a2b9f9cc1e17a66e6d75a3dea316 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 4 Feb 2026 19:20:38 +0100 Subject: [PATCH 14/17] Rewrite n0_subband_power_avg_dB calculation with better locality --- openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 6005c39343..c11741eb40 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -184,7 +184,6 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy } //rb } // symb int nb_rb=0; - int64_t n0_subband_tot=0; int32_t n0_subband_tot_perANT[frame_parms->nb_antennas_rx]; memset(n0_subband_tot_perANT, 0, sizeof(n0_subband_tot_perANT)); @@ -208,14 +207,15 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy n0_subband_tot_perPRB /= frame_parms->nb_antennas_rx; measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_subband_tot_perPRB); LOG_D(NR_PHY,"n0_subband_power_tot_dB[%d] => %d, over %d symbols\n",rb,measurements->n0_subband_power_tot_dB[rb],nb_symb[rb]); - n0_subband_tot += n0_subband_tot_perPRB; nb_rb++; } } if (nb_rb>0) { - measurements->n0_subband_power_avg_dB = dB_fixed(n0_subband_tot/nb_rb); - for (int aarx=0;aarxnb_antennas_rx;aarx++) { - measurements->n0_subband_power_avg_perANT_dB[aarx] = dB_fixed(n0_subband_tot_perANT[aarx]/nb_rb); - } + int64_t n0_subband_tot = 0; + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + measurements->n0_subband_power_avg_perANT_dB[aarx] = dB_fixed(n0_subband_tot_perANT[aarx] / nb_rb); + n0_subband_tot += n0_subband_tot_perANT[aarx]; + } + measurements->n0_subband_power_avg_dB = dB_fixed(n0_subband_tot / nb_rb); } } From 95c8fa468ac577f17924a18491f3712529b750fe Mon Sep 17 00:00:00 2001 From: andrewse Date: Thu, 4 Dec 2025 11:28:31 +0000 Subject: [PATCH 15/17] fhi_72: Track delay processing via atomic variable Add xran_queue_length atomic variable to count the number of messages in oran_sync_fifo (as notifiedFIFO_t does not do this). Use this to tolerate some double messages (e.g. excessive processing delay), but start to skip if messages accumulate. Prior to this change, "Detected double sync message" was printed each time there was more than one message, which reflected the previous behavior when using polling, but the gNB might catch up if it is only once. The new logic ensure that we don't skip individual slots but do so once messages start to accumulate. --- radio/fhi_72/oaioran.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 31c754738d..cea202346c 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "xran_fh_o_du.h" #include "xran_compression.h" #include "armral_bfp_compression.h" @@ -56,6 +57,7 @@ int xran_is_prach_slot(uint8_t PortId, uint32_t subframe_id, uint32_t slot_id); #ifndef USE_POLLING extern notifiedFIFO_t oran_sync_fifo; +atomic_int xran_queue_length = 0; #else volatile oran_sync_info_t oran_sync_info = {0}; #endif @@ -136,6 +138,7 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) info->sl = slot2; info->f = frame; LOG_D(HW, "Push %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, info->sl, slot, ru_id, subframe, last_slot); + atomic_fetch_add(&xran_queue_length, 1); pushNotifiedFIFO(&oran_sync_fifo, req); #else LOG_D(HW, "Writing %d.%d.%d (slot %d, subframe %d,last_slot %d)\n", frame, slot2, ru_id, slot, subframe, last_slot); @@ -294,20 +297,29 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) struct xran_common_counters x_counters[XRAN_PORTS_NUM]; static int outcnt = 0; #ifndef USE_POLLING - // pull next even from oran_sync_fifo + // pull next event 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; - } - + atomic_fetch_sub(&xran_queue_length, 1); oran_sync_info_t *info = NotifiedFifoData(res); +#define MAX_QUEUE_LENGTH_NO_JUMP 3 + if (xran_queue_length > 0 && xran_queue_length < MAX_QUEUE_LENGTH_NO_JUMP) { + LOG_D(HW, "%4d.%2d TTI processing delay detected\n", info->f, info->sl); + } else if (xran_queue_length >= MAX_QUEUE_LENGTH_NO_JUMP) { + uint32_t old_f = info->f; + uint32_t old_sl = info->sl; + // set the frame/slot info to what is in the last message + notifiedFIFO_elt_t *f; + while ((f = pollNotifiedFIFO(&oran_sync_fifo)) != NULL) { + atomic_fetch_sub(&xran_queue_length, 1); + delNotifiedFIFO_elt(res); + res = f; + } + info = NotifiedFifoData(res); + LOG_W(HW, "TTI processing delay detected, skipping %4d.%2d => %4d.%2d\n", old_f, old_sl, info->f, info->sl); + DevAssert(xran_queue_length == 0); + } + *slot = info->sl; *frame = info->f; delNotifiedFIFO_elt(res); From 269880f89d0ad00bc349476bc86f93be404a2324 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 3 Feb 2026 09:30:00 +0100 Subject: [PATCH 16/17] change in libconfig for string to reject an input that is not of type string with error message --- common/config/libconfig/config_libconfig.c | 55 ++++++++++++++++++---- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/common/config/libconfig/config_libconfig.c b/common/config/libconfig/config_libconfig.c index 0770fb2af8..e265c93207 100644 --- a/common/config/libconfig/config_libconfig.c +++ b/common/config/libconfig/config_libconfig.c @@ -319,6 +319,32 @@ int config_libconfig_set(configmodule_interface_t *cfg, paramdef_t *cfgoptions, } } +static const char *config_type_to_name(int type) +{ + switch (type) { + case CONFIG_TYPE_NONE: + return "none"; + case CONFIG_TYPE_GROUP: + return "group"; + case CONFIG_TYPE_INT: + return "integer"; + case CONFIG_TYPE_INT64: + return "64-bit integer"; + case CONFIG_TYPE_FLOAT: + return "float"; + case CONFIG_TYPE_STRING: + return "string"; + case CONFIG_TYPE_BOOL: + return "boolean"; + case CONFIG_TYPE_ARRAY: + return "array"; + case CONFIG_TYPE_LIST: + return "list"; + default: + return "unknown"; + } +} + int config_libconfig_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions, int numoptions, char *prefix) { config_setting_t *setting; @@ -348,17 +374,26 @@ int config_libconfig_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions, switch(cfgoptions[i].type) { case TYPE_STRING: - if ( config_lookup_string(&(libconfig_privdata.cfg), cfgpath, (const char**)&str)) { - config_check_valptr(cfg, &cfgoptions[i], 1, strlen(str) + 1); - if ( strlen(str)+1 > cfgoptions[i].numelt ) - fprintf(stderr,"[LIBCONFIG] %s: %s exceeds maximum length of %i bytes, value truncated\n", - cfgpath,str,cfgoptions[i].numelt); - snprintf( *cfgoptions[i].strptr , cfgoptions[i].numelt, "%s", str); - printf_params(cfg, "[LIBCONFIG] %s: \"%s\"\n", cfgpath, *cfgoptions[i].strptr); - } else { + setting = config_lookup(&(libconfig_privdata.cfg), cfgpath); + if (setting != NULL) { + int type = config_setting_type(setting); + if (type == CONFIG_TYPE_STRING) { + const char *strng = config_setting_get_string(setting); + config_check_valptr(cfg, &cfgoptions[i], 1, strlen(strng) + 1); + if (strlen(strng) + 1 > cfgoptions[i].numelt) + fprintf(stderr, + "[LIBCONFIG] %s: %s exceeds maximum length of %i bytes, value truncated\n", + cfgpath, + strng, + cfgoptions[i].numelt); + snprintf(*cfgoptions[i].strptr, cfgoptions[i].numelt, "%s", strng); + printf_params(cfg, "[LIBCONFIG] %s: \"%s\"\n", cfgpath, *cfgoptions[i].strptr); + } else { + fprintf(stderr,"[LIBCONFIG] expected a string input for %s but got type %s\n", cfgpath, config_type_to_name(type)); + fatalerror = 1; + } + } else defval = config_common_getdefault(cfg, &cfgoptions[i], prefix); - } - break; case TYPE_STRINGLIST: From 0c2a9384d07e8e92a0da5f136630a632d0d7ae2c Mon Sep 17 00:00:00 2001 From: rmagueta Date: Sat, 24 Jan 2026 09:45:40 +0000 Subject: [PATCH 17/17] Removing the duplicate loop --- .../PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 93 +++++++++---------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 4 - 2 files changed, 45 insertions(+), 52 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index aa0da63558..ba4d192629 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1164,12 +1164,11 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, int max_ch = 0; uint32_t nvar = 0; int end_symbol = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols; - for(uint8_t symbol = rel15_ul->start_symbol_index; symbol < end_symbol; symbol++) { + for (uint8_t symbol = rel15_ul->start_symbol_index; symbol < end_symbol; symbol++) { uint8_t dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag); - - if (dmrs_symbol_flag == 1) { + if (dmrs_symbol_flag == 1) { for (int nl = 0; nl < rel15_ul->nrOfLayers; nl++) { uint32_t nvar_tmp = 0; nr_pusch_channel_estimation(gNB, @@ -1187,56 +1186,54 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, pusch_ch_est_dmrs_pos_slot_mem); nvar += nvar_tmp; } - - allocCast2D(n0_subband_power, - unsigned int, - gNB->measurements.n0_subband_power, - frame_parms->nb_antennas_rx, - frame_parms->N_RB_UL, - false); - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - if (symbol == rel15_ul->start_symbol_index) { - pusch_vars->ulsch_power[aarx] = 0; - pusch_vars->ulsch_noise_power[aarx] = 0; - } - - int64_t symb_energy = 0; - int start_sc = (rel15_ul->bwp_start + rel15_ul->rb_start) * NR_NB_SC_PER_RB; - int middle_sc = frame_parms->ofdm_symbol_size - frame_parms->first_carrier_offset; - int end_sc = (start_sc + rel15_ul->rb_size * NR_NB_SC_PER_RB - 1) % frame_parms->ofdm_symbol_size; - - for (int s = rel15_ul->start_symbol_index; s < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); s++) { - int offset0 = ((slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot + s) * frame_parms->ofdm_symbol_size; - int offset = offset0 + (frame_parms->first_carrier_offset + start_sc) % frame_parms->ofdm_symbol_size; - c16_t *ul_ch = &gNB->common_vars.rxdataF[beam_nb][aarx][offset]; - if (end_sc < start_sc) { - int64_t symb_energy_aux = signal_energy_nodc(ul_ch, middle_sc - start_sc) * (middle_sc - start_sc); - ul_ch = &gNB->common_vars.rxdataF[beam_nb][aarx][offset0]; - symb_energy_aux += (signal_energy_nodc(ul_ch, end_sc + 1) * (end_sc + 1)); - symb_energy += symb_energy_aux / (rel15_ul->rb_size * NR_NB_SC_PER_RB); - } else { - symb_energy += signal_energy_nodc(ul_ch, rel15_ul->rb_size * NR_NB_SC_PER_RB); - } - } - pusch_vars->ulsch_power[aarx] += (symb_energy / rel15_ul->nr_of_symbols); - - pusch_vars->ulsch_noise_power[aarx] += - average_u32(&n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start], rel15_ul->rb_size); - - LOG_D(PHY, - "aa %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n", - aarx, - rel15_ul->bwp_start, - rel15_ul->rb_start, - rel15_ul->rb_size, - pusch_vars->ulsch_power[aarx], - pusch_vars->ulsch_noise_power[aarx]); - } } } nvar /= (rel15_ul->nr_of_symbols * rel15_ul->nrOfLayers * frame_parms->nb_antennas_rx); + allocCast2D(n0_subband_power, + unsigned int, + gNB->measurements.n0_subband_power, + frame_parms->nb_antennas_rx, + frame_parms->N_RB_UL, + false); + + int start_sc = (rel15_ul->bwp_start + rel15_ul->rb_start) * NR_NB_SC_PER_RB; + int middle_sc = frame_parms->ofdm_symbol_size - frame_parms->first_carrier_offset; + int end_sc = (start_sc + rel15_ul->rb_size * NR_NB_SC_PER_RB - 1) % frame_parms->ofdm_symbol_size; + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + pusch_vars->ulsch_power[aarx] = 0; + pusch_vars->ulsch_noise_power[aarx] = 0; + int64_t symb_energy = 0; + + for (uint8_t symbol = rel15_ul->start_symbol_index; symbol < end_symbol; symbol++) { + int offset0 = ((slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot + symbol) * frame_parms->ofdm_symbol_size; + int offset = offset0 + (frame_parms->first_carrier_offset + start_sc) % frame_parms->ofdm_symbol_size; + c16_t *ul_ch = &gNB->common_vars.rxdataF[beam_nb][aarx][offset]; + if (end_sc < start_sc) { + int64_t symb_energy_aux = signal_energy_nodc(ul_ch, middle_sc - start_sc) * (middle_sc - start_sc); + ul_ch = &gNB->common_vars.rxdataF[beam_nb][aarx][offset0]; + symb_energy_aux += (signal_energy_nodc(ul_ch, end_sc + 1) * (end_sc + 1)); + symb_energy += symb_energy_aux / (rel15_ul->rb_size * NR_NB_SC_PER_RB); + } else { + symb_energy += signal_energy_nodc(ul_ch, rel15_ul->rb_size * NR_NB_SC_PER_RB); + } + } + pusch_vars->ulsch_power[aarx] += (symb_energy / rel15_ul->nr_of_symbols); + + pusch_vars->ulsch_noise_power[aarx] += + average_u32(&n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start], rel15_ul->rb_size); + + LOG_D(PHY, + "aa %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n", + aarx, + rel15_ul->bwp_start, + rel15_ul->rb_start, + rel15_ul->rb_size, + pusch_vars->ulsch_power[aarx], + pusch_vars->ulsch_noise_power[aarx]); + } + // averaging time domain channel estimates if (gNB->chest_time == 1) nr_chest_time_domain_avg(frame_parms, diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index ff82310d29..5f75a04b05 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -1083,8 +1083,6 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled)) continue; LOG_D(PHY, "PUSCH ID %d with RNTI %x detection started in frame %d slot %d\n", ULSCH_id, ulsch->rnti, frame_rx, slot_rx); - nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; - int num_dmrs = count_bits64_with_mask(pdu->ul_dmrs_symb_pos, 0, NR_NUMBER_OF_SYMBOLS_PER_SLOT); #ifdef DEBUG_RXDATA RU_t *ru = gNB->RU_list[0]; @@ -1124,9 +1122,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N pusch_vars->ulsch_power_tot = 0; pusch_vars->ulsch_noise_power_tot = 0; for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { - pusch_vars->ulsch_power[aarx] /= num_dmrs; pusch_vars->ulsch_power_tot += pusch_vars->ulsch_power[aarx]; - pusch_vars->ulsch_noise_power[aarx] /= num_dmrs; pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx]; } if (dB_fixed_x10(pusch_vars->ulsch_power_tot) < dB_fixed_x10(pusch_vars->ulsch_noise_power_tot) + gNB->pusch_thres) {