Skip to content

feat(nfapi): OAI nFAPI Delay Management implementation#242

Open
dong881 wants to merge 12 commits into
duranta-project:developfrom
dong881:nfapi-DelayManagement
Open

feat(nfapi): OAI nFAPI Delay Management implementation#242
dong881 wants to merge 12 commits into
duranta-project:developfrom
dong881:nfapi-DelayManagement

Conversation

@dong881

@dong881 dong881 commented Jun 28, 2026

Copy link
Copy Markdown

This Pull Request introduces the clean, production-ready OAI nFAPI Delay Management features (VNF autonomous timing thread, adaptive EWMA delay-management controller, etc.) along with the NULL pointer stability bugfix.

Copilot AI review requested due to automatic review settings June 28, 2026 17:11
@linux-foundation-easycla

linux-foundation-easycla Bot commented Jun 28, 2026

Copy link
Copy Markdown

CLA Missing ID

@durantabot

Copy link
Copy Markdown
Collaborator

CI Build: #529 | Not performing CI due to the absence of one of the following mandatory labels:

  • documentation Documentation-related changes or updates. (don't perform any stages)
  • BUILD-ONLY Execute build stages only for code improvements with no impact on 4G/5G functionality. (execute only build stages)
  • 4G-LTE Perform 4G Tests (perform 4G tests)
  • 5G-NR Perform 5G Tests (perform 5G tests)
  • nrUE Run only 5G UE tests (physims included, LDPC tests excluded). (perform only 5G-UE related tests including physims excluding LDPC tests)
  • CI Perform both 4G and 5G tests (perform both 4G and 5G tests)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds OAI nFAPI Delay Management for NR, including a VNF autonomous timing thread and updated PNF/VNF timing/jitter reporting, and also improves stability around PRACH handling and thread naming.

Changes:

  • Implement VNF-side autonomous timing thread and EWMA-based slot-ahead delay controller driven by TIMING_INFO.
  • Add PNF-side RFC3550-style jitter calculation and richer timing window checks; extend NR timing info fields (including renames for TX_DATA timing/jitter fields).
  • Improve PRACH segmented packet handling in the O-RAN FHI path and relax hard asserts on queue-length conditions during delay situations.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
radio/fhi_72/oaioran.c Adds PRACH segmentation support during PRACH read/decompression and relaxes strict asserts on delay conditions.
nfapi/open-nFAPI/vnf/src/vnf_p7.c Adds NR timing extraction, EWMA delay-management controller, and wrap-safe time computations; refactors UL node sync handling.
nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c Adjusts socket IP_TOS and initializes new timing/mutex fields for P7 connection nodes.
nfapi/open-nFAPI/vnf/src/vnf_interface.c Uses user-configured timing parameters instead of hardcoded defaults during PHY allocation.
nfapi/open-nFAPI/vnf/public_inc/nfapi_vnf_interface.h Widens timing_window type and adds timing config fields to VNF config.
nfapi/open-nFAPI/vnf/inc/vnf_p7.h Introduces delay-management constants/state, mutex/condvar fields, and timing stats types.
nfapi/open-nFAPI/pnf/src/pnf_p7.c Implements RFC3550 jitter tracking, wrap-safe time diffs, timing-window enforcement, and periodic/aperiodic timing-info send logic changes.
nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c Initializes PNF config defaults for timing-info sending and improves cleanup of allocated buffers.
nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h Adds per-message receive timestamps into the PNF slot buffer for timing calculations.
nfapi/open-nFAPI/pnf/inc/pnf_p7.h Adds jitter state, timing trigger fields, and buffer sizing constants for PNF P7 processing.
nfapi/open-nFAPI/nfapi/src/nfapi_nr_p7.c Updates packing/unpacking for renamed NR timing-info TX_DATA fields.
nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h Renames NR timing-info TX_DATA fields to match updated pack/unpack and usage.
nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h Widens NR timing_window TLV from uint8 to uint16.
nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c Packs/unpacks widened timing-window TLV and adds TLVs for per-message timing offsets.
nfapi/oai_integration/socket/socket_vnf.c Sets IP_TOS for VNF socket to prioritize timing-sensitive traffic.
nfapi/oai_integration/socket/socket_pnf.c Allocates RX/reassembly buffers and sets IP_TOS for PNF socket; adjusts slot handling behavior.
nfapi/oai_integration/nfapi_vnf.h Widens timing window types and adds timing offset configuration fields.
nfapi/oai_integration/nfapi_vnf.c Adds autonomous VNF timing thread, timing-info configuration wiring, offset TLV wiring, and adjusts message ordering.
nfapi/oai_integration/nfapi_pnf.c Wires timing offsets and timing-info configuration from VNF into PNF P7 behavior; gates slot indications under WLS.
common/utils/system.c Avoids aborting on pthread_setname_np() failure; logs error instead.

Comment thread radio/fhi_72/oaioran.c Outdated
Comment on lines +444 to +460
int num_total_prbs = 0;
for (int i = 0; i < nRxPkt; i++) {
num_total_prbs += p_rx_packet_ctl->nRBSize[i];
}
int16_t local_dst[num_total_prbs * 2 * N_SC_PER_PRB] __attribute__((aligned(64)));
memset(local_dst, 0, sizeof(local_dst));

for (int pkt_idx = 0; pkt_idx < nRxPkt; pkt_idx++) {
src = (int16_t *)p_rx_packet_ctl->pData[pkt_idx];
if (src == NULL) {
LOG_E(HW, "read_prach %d.%d.%d saa = %d: src[%d] = NULL!!\n", *frame, *slot, sym_idx, aa, pkt_idx);
continue;
}
int num_prbu_local = p_rx_packet_ctl->nRBSize[pkt_idx];
int start_prbu = p_rx_packet_ctl->nRBStart[pkt_idx];
int16_t *decom_dst = local_dst + (start_prbu - p_rx_packet_ctl->nRBStart[0]) * N_SC_PER_PRB * 2;

Comment on lines +121 to +127
uint64_t pnf_timehr_to_us(pnf_p7_t* pnf_p7, uint32_t time_hr)
{
uint32_t sec = TIMEHR_SEC(time_hr);
uint32_t usec = TIMEHR_USEC(time_hr);
// Convert to 64-bit microseconds (relative, will wrap at 4096 seconds)
return (uint64_t)sec * 1000000ULL + (uint64_t)usec;
}
Comment on lines +193 to +198
/* Function Declaration */
// Extract timing info points from a timing_info message
// Returns the number of valid stats extracted (0-8)
int vnf_nr_extract_timing_info(const nfapi_nr_timing_info_t *ind,
nfapi_vnf_p7_connection_info_t *p7_info,
vnf_timing_stats_t *out_stats);
Comment thread nfapi/open-nFAPI/vnf/src/vnf_p7.c Outdated
Comment on lines +224 to +242
static int32_t ceil_div_pos_i32(int32_t num, int32_t den)
{
if (den <= 0)
return 0;

if (num <= 0)
return 0;

return (num + den - 1) / den;
}

static int32_t abs_i32(int32_t v)
{
return v < 0 ? -v : v;
}
static inline int32_t p7_max_i32(int32_t a, int32_t b)
{
return a > b ? a : b;
}
Comment thread nfapi/open-nFAPI/vnf/src/vnf_p7.c Outdated
Comment on lines +281 to +284
static inline int p7_ewma_effectively_zero_i32(
int32_t value,
int32_t denom)
{
Comment on lines +2136 to +2141
pthread_mutex_lock(&p7_con->mutex);
p7_con->timing_info_accum_count = 0;
p7_con->timing_info_accum_worst_late = INT32_MIN;
pthread_mutex_unlock(&p7_con->mutex);

vnf_nr_delay_management(p7_con, &aggregated_stats);
Comment thread nfapi/oai_integration/nfapi_vnf.c Outdated
p7_info->sync_slot_counter++;
}

int target_ind_dec = (sfnslot_dec + p7_info->slot_ahead) % max_sfnslotdec;
Comment thread nfapi/oai_integration/nfapi_vnf.c Outdated
nfapi_vnf_p7_connection_info_t *p7_info = NULL;

while (1) {
if (nr_start_resp_received) {
Comment thread nfapi/oai_integration/nfapi_vnf.c Outdated
int nr_start_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_start_response_scf_t *resp) {
UNUSED(config);
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Received NFAPI_START_RESP idx:%d phy_id:%d\n", p5_idx, resp->header.phy_id);
nr_start_resp_received = 1;
@dong881 dong881 force-pushed the nfapi-DelayManagement branch from 8fc8c91 to 44a7d01 Compare June 29, 2026 02:06
@durantabot

Copy link
Copy Markdown
Collaborator

CI Build: #530 | Not performing CI due to the absence of one of the following mandatory labels:

  • documentation Documentation-related changes or updates. (don't perform any stages)
  • BUILD-ONLY Execute build stages only for code improvements with no impact on 4G/5G functionality. (execute only build stages)
  • 4G-LTE Perform 4G Tests (perform 4G tests)
  • 5G-NR Perform 5G Tests (perform 5G tests)
  • nrUE Run only 5G UE tests (physims included, LDPC tests excluded). (perform only 5G-UE related tests including physims excluding LDPC tests)
  • CI Perform both 4G and 5G tests (perform both 4G and 5G tests)

Comment thread radio/fhi_72/oaioran.c Outdated
AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMapPrach == NULL. Aborting.\n", cc_id, tti % XRAN_N_FE_BUF_LEN, ant_id);
for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
AssertFatal(pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt <= 1, "PRACH segmentation is not supported\n");
if (pRbMap->sFrontHaulRxPacketCtrl[sym_id].nRxPkt > 1) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please open a separate PR for all xran-related changes. That just does not belong together with nFAPI related changes, the set of reviewers is different, and needs separate attention

@rorsc rorsc added the BUILD-ONLY Execute build stages only for code improvements with no impact on 4G/5G functionality. label Jun 29, 2026
@rorsc rorsc requested a review from rubensoaressilva June 29, 2026 07:42
Make thread-name assignment failures fatal in threadCreate() so a misconfigured
RT thread is caught immediately during bring-up. Dev hardening, not required
upstream.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
@dong881 dong881 force-pushed the nfapi-DelayManagement branch from 44a7d01 to d60ebf6 Compare June 30, 2026 06:47
@dong881 dong881 changed the title feat(nfapi/vnf): OAI nFAPI Delay Management implementation feat(nfapi): OAI nFAPI Delay Management implementation Jun 30, 2026
@dong881 dong881 force-pushed the nfapi-DelayManagement branch 2 times, most recently from 29b1323 to 54e3c17 Compare June 30, 2026 07:56
Comment on lines -725 to +744
int iptos_value = 0;
int iptos_value = 184;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does this value of 184 come from?
If it's supposed to be 'IPTOS_DSCP_EF', include <netinet/ip.h> and use the #define.
If it's not, just add a small comment on what '184' is doing.


// configure the UDP socket options
int iptos_value = 0;
int iptos_value = 184;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, you can even include <netinet/ip.h> in socket_common.h, since it would be used by both VNF and PNF

Comment on lines +947 to -952
if (sched_response.TX_req.Number_of_PDUs > 0)
oai_nfapi_tx_data_req(&sched_response.TX_req);

if (sched_response.DL_req.dl_tti_request_body.nPDUs > 0)
oai_nfapi_dl_tti_req(&sched_response.DL_req);

if (sched_response.UL_tti_req.n_pdus > 0)
oai_nfapi_ul_tti_req(&sched_response.UL_tti_req);

if (sched_response.TX_req.Number_of_PDUs > 0)
oai_nfapi_tx_data_req(&sched_response.TX_req);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to change the message order here?
in SCF222.10.04 Figure 2-21 you can see it is in the order that was defined, and in SCF225.3.0 Section 2.1.3.5 it states that the message order defined in FAPI also applies for nFAPI.

p7_vnf->config->send_p7_msg = &vnf_nr_send_p7_msg;
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI P7 start thread %s\n", __FUNCTION__);
threadCreate(&vnf_p7_start_pthread, &vnf_nr_start_p7_thread, p7_vnf->config, "vnf_p7_thread", -1, OAI_PRIORITY_RT);
threadCreate(&vnf_p7_start_pthread, &vnf_nr_start_p7_thread, p7_vnf->config, "vnf_p7_thread", 14, OAI_PRIORITY_RT);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should avoid pinning to specific cores, if it's really needed, add a new parameter to the config file for the use to be able to set the core to pin to ( default -1 ), similarly to the pinning of the nvIPC thread.

#ifndef ENABLE_WLS
// Start VNF autonomous timing thread
pthread_t t;
threadCreate(&t, &vnf_timing_thread, p7_vnf, "vnf_timing", 15, OAI_PRIORITY_RT_MAX);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, don't pin to a specific core.

if(p7_vnf->thread_started == 0) {
pthread_t vnf_p7_thread;
threadCreate(&vnf_p7_thread, &configure_nr_p7_vnf, p7_vnf, "vnf_p7_thread", -1, OAI_PRIORITY_RT);
threadCreate(&vnf_p7_thread, &configure_nr_p7_vnf, p7_vnf, "vnf_p7_thread", 14, OAI_PRIORITY_RT);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above

*/

int iptos_value = 0;
int iptos_value = 184;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, you can include <netinet/ip.h> and use IPTOS_DSCP_EF

Ming-Hong HSU, BMW Lab@NTUST added 11 commits June 30, 2026 16:40
Shouldn't have duplicate slot increment at PNF side

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
Rename tx_data_request_* timing fields to tx_data_* in NR timing-related
structures and handling paths. This removes naming ambiguity and aligns
with current SCF 225 terminology used by timing info exchange.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
SCF 225 allows timing_window up to 30000us, which exceeds uint8 capacity.
Promote timing_window-related fields and pack/unpack paths to uint16 so
configuration values are represented consistently across VNF/PNF interfaces.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
Add DL_TTI/UL_TTI/UL_DCI/TX_DATA per-message timing-offset TLVs to the PARAM
response and CONFIG request (pack/unpack in nr_fapi_p5.c, PNF/VNF config structs)
so the VNF can tell the PNF how far ahead each message type is sent.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
Measure per-message P7 arrival timing against the expected window (timing check,
slot-diff, in-window tests), accumulate worst-case late/early margins and jitter
per message type, and pack them into the timing-info report
(pnf_nr_pack_and_send_timing_info). Reset slot_start on start/stop and count late
DL/UL/DCI/TX requests.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
Pre-allocate an rx message buffer and a reassembly buffer (sizes in pnf_p7.h) and
reassemble P7 messages fragmented at MTU boundaries in the message pump; free the
buffers on config destroy.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
Parse the PNF timing-info report (vnf_nr_handle_timing_info /
vnf_nr_extract_timing_info) and aggregate worst-late and jitter across message
types into per-connection state for the pacing logic to consume.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
Add a self-paced VNF timing thread that derives the numerology, sleeps to each
slot boundary (clock_nanosleep), publishes sfn/slot under lock and issues MAC slot
indications, catching up in bounded bursts under load and yielding on extreme lag.
Send TX_DATA ahead of DL_TTI in the slot-indication path.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
Add UL node-sync handling (vnf_nr_handle_ul_node_sync) with proportional
micro-steering of the slot phase and a drift monitor, plus the slot-time helpers
used to compute the dynamic sleep target.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
Expose timing_window and periodic/aperiodic timing mode and period through the VNF
config, add tx_data connection routing and set the RT thread priorities used to set
up the P7 timing path.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
Add vnf_nr_delay_management(): an EWMA controller that tracks mean lateness and
jitter deviation from the aggregated timing info and adjusts slot_ahead (increase
by ceil((EWMA+Dev)/slot_dur) when late, decrease one slot with >=4-sigma early
margin), gated to one timing_info_period, wired into vnf_nr_handle_timing_info.
Without this commit the pipeline still runs, with a fixed non-adaptive slot_ahead.

Signed-off-by: Ming-Hong HSU, BMW Lab@NTUST <m11302209@gapps.ntust.edu.tw>
@dong881 dong881 force-pushed the nfapi-DelayManagement branch from 54e3c17 to f46c8dd Compare June 30, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BUILD-ONLY Execute build stages only for code improvements with no impact on 4G/5G functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants