Skip to content

nFAPI Split Certification

nFAPI Split Certification is part of Stage 3 of Cloud Native Telecom Certification, alongside the CU/DU Split. Where the CU/DU work certifies a gNB split high in the stack, at F1 and E1, this work certifies the split one layer lower: the boundary between L2 (MAC) and L1 (PHY), carried over nFAPI.

It certifies two product classes, the PNF (the L1/PHY end) and the VNF (the L2 end that drives it), over the real nFAPI interface: P5 for configuration and P7 for the slot loop. You point the framework at a running L1/L2 split, run it, and get a graded verdict per product class and, on a clean pass, a certificate.

Everything described here lives in github.com/TOSSI-Foundation/CNTC, under Apache-2.0.

The CNTC RAN certification framework for the L1 and L2 nFAPI split, in three parts. The nFAPI certification pipeline runs seven stages: adapter finds and starts the stack, bring up starts the VNF then the PNF, drive runs one real UE attach, capture tears down and flushes the pcaps, decode uses CNTC's own decoder to produce JSON, grade applies a catalog per class, and certify applies the essential gate. The first five stages are measurement by ranbench; the last two are judgement by cntc. Part one, the ranbench engine, carries one adapter per nFAPI stack, fapi_oai for pure OAI and fapi_split for xFAPI; the adapter finds the stack, starts it, resolves endpoints and captures. The UE is an OAI nr-UE over an rfsimulator radio with no RF hardware, doing 5G-AKA, RRC and NAS. Observers decode the wire with an nFAPI decoder and capture P5 and P7. The interfaces decoded are P5 over SCTP per SCF225, P7 over UDP per SCF225, and message IDs per SCF222. One campaign brings two classes up, runs one UE attach, tears down and flushes, and writes a results.json on one shared schema. Part two is the gNB L1 and L2 under test, bring-your-own. The peers are a UE simulator over rfsim, an AMF over N2 and a UPF over N3. The PNF, the Physical Network Function at L1 and PHY, has 26 tests of which 14 are essential, with functions PHY, IFFT and FFT, RACH and IQ; it terminates P5 responses, P7 SLOT indication, and CRC, RX_DATA and UCI; its obligations under SCF222 and SCF225 are SLOT.indication every slot, RACH.indication on preamble, and no P7 before START.response. The VNF, the L2 driver end of nFAPI, has 15 tests of which 9 are essential, with functions MAC, RLC, PDCP and RRC; it terminates P5 PARAM, CONFIG and START, P7 DL_TTI and UL_TTI, and TX_DATA and UL_DCI; its obligations are PARAM then CONFIG then START in order, staying inside advertised capabilities, and no TTI request for a slot the PHY has passed. In total 41 tests, 23 essential, two certificates. Part three is the CNTC umbrella: it reads campaigns results.json, runs a versioned per-class verdict evaluation, holds PNF-conformance and VNF-conformance Level 1 catalogs, applies an essential gate returning pass, fail or incomplete, and outputs a scorecard, certificate and dashboard. Standards alignment covers SCF 222, SCF 225, 3GPP TS 38.321 and 3GPP TR 38.801.

The nFAPI interface and its certification scope

A gNB can be split in more than one place, and which split you deploy decides what a certificate can even mean. 3GPP defines eight functional split options between the RRC layer and the radio (TR 38.801). The CU/DU work certifies Option 2 (F1) and the control and user split inside the CU (E1). nFAPI is a different boundary.

The Small Cell Forum defines the interface between MAC and PHY as FAPI (SCF 222), and its networked form, nFAPI (SCF 225), wraps that interface in a transport so L2 and L1 can be separate products from separate vendors. That is functional split Option 6, and it is exactly the kind of boundary a certification belongs at: two independently supplied halves that must interoperate against a published specification.

SplitInterfaceSeparatesCNTC
Option 2F1CU from DUCU/DU Split
Option 2 (control/user)E1CU-CP from CU-UPCU/DU Split
Option 6FAPI, nFAPIL2 from L1, MAC from PHYthis document
Option 7.2xOpen FronthaulO-DU from O-RUroadmap

Relationship to 3GPP SCAS product classes

Every CU/DU catalog in CNTC anchors to 3GPP TS 33.523, which defines gNB-CU-CP, gNB-CU-UP and gNB-DU as product classes with security assurance requirements. 3GPP defines no product class for an L1, and there is no Security Assurance Specification for the L1/L2 split. The anchors for this work are the Small Cell Forum's, and the PNF and VNF names are the Small Cell Forum's own:

  • SCF 222, 5G FAPI: PHY API Specification, 10th edition (July 2025). The P5 configuration and P7 slot message definitions and procedures.
  • SCF 225, 5G nFAPI specifications. The networked form of SCF 222: transport, framing, and the PNF-level procedures. SCF 225 wraps SCF 222 to form the Option 6 interface.

A certificate issued against these catalogs asserts conformance to an SCF interface specification in the PNF or VNF role. It is not a 3GPP SCAS product class certificate, and the scorecard says so on every run. This is a deliberate honesty boundary, not a caveat buried in a footnote.

The two product classes

The split defines two roles on one wire.

Product classSCF roleWhat it isMessages drivenTests
PNFPhysical Network Functionthe L1/PHY endanswers P5 setup, drives the P7 slot loop26 (14 essential)
VNFVirtual Network Functionthe L2 end that terminates nFAPI northbound of the PNFissues the P5 setup, issues the P7 slot requests15 (9 essential)

41 Level-1 requirements in total, 23 of them essential. The two verdicts are independent. One class can certify while the other fails, which is what happens on the reference stack.

Topology diagram for the nFAPI split certification rig. A UE simulator connects over the air to the PNF, the L1, whose blocks are SSB, PDCCH, PRACH, PDSCH, PUCCH and PUSCH. The PNF connects to the VNF, the L2 to L3 end, over the FAPI and nFAPI interface, which carries 41 tests. The VNF's blocks are RRC, PDCP, GTP, F1AP, RLC, NGAP, Scheduler and DU Management. Northbound the VNF connects to an AMF over N2 using NGAP, carrying 12 tests, and to a UPF over N3 using GTP-U, carrying 6 tests. The AMF is labelled as the core acting as a peer and the UPF as the route to the data network; neither is the subject of the certificate.

A note on what "VNF" means here. VNF is a role on the nFAPI interface, not a claim about which layers a product hosts. Where the VNF role is filled by a translator in front of a separate L2, this catalog judges the translator, because it is the thing that speaks nFAPI. A VNF has two sides: its southbound nFAPI link is on the wire and is judged; its northbound side is not part of this interface and is not claimed. Where a deployment carries the VNF's other side over shared memory or any transport that cannot be captured, that side is not evidenced by anything here.

Architecture

The framework is in three parts.

Part one is the ranbench engine. It carries one adapter per nFAPI stack, a UE supplied by ranbench, observers that decode the wire, and the interface definitions the results are judged against. The adapter finds the stack, starts it in the required order, drives one attach, tears it down so the captures flush, and decodes to a results.json. The UE is the OpenAirInterface nr-UE over the rfsimulator virtual radio, no RF hardware, doing 5G-AKA, RRC and NAS.

Part two is the L1/L2 node under test, bring-your-own. The peers are not certified: the UE simulator, and the core (AMF and UPF) that the L2 attaches through. The two product classes are the PNF and the VNF. One nFAPI capture is read in both directions, the PNF to VNF direction judged against the PNF catalog and the VNF to PNF direction against the VNF catalog. This is exactly how F1-C is read once and judged twice for the O-DU and the O-CU-CP in the CU/DU work.

Part three is the cntc umbrella. It holds the per-product-class catalogs, the versioned grader that produces one verdict per class, an essential gate returning PASS, FAIL or INCOMPLETE where not evaluated is not a pass, and outputs of scorecard, certificate and dashboard.

Reference stacks

The same catalogs, observer and suites certify two different deployments without change.

pure OAI (configs/fapi-oai.yaml)cross-vendor (configs/fapi-split.yaml)
PNF (L1)OAI nr-softmodem --nfapi PNFOAI nr-softmodem --nfapi PNF (same binary)
VNFOAI nr-softmodem --nfapi VNF (carries L2 and L3)xFAPI, in front of an OCUDU L2
CUnone: the VNF terminates N2/N3 itselfOCUDU CU over F1
processestwo (VNF, PNF)four (CU, VNF, PNF, L2)
adapterfapi_oai (subclasses fapi_split)fapi_split
buildOAI_GNB=1 ./scripts/bootstrap_ranbench.shFAPI=1 ./scripts/bootstrap_ranbench.sh

Because the PNF is the same OAI L1 in both stacks, its verdicts should match across the two, which is a useful cross-check. The cross-vendor stack proves the interface does what it exists for: an L1 from one project and an L2 from another, interoperating against a published specification with no shared code.

Decoding nFAPI

Every other CNTC interface is decoded with tshark. nFAPI is not, and the reason is a real defect in the standard tooling.

The 5G NR nFAPI message IDs overlap the LTE nFAPI IDs with different meanings. A dissector written for LTE names NR messages confidently and wrongly. On the reference tshark, SLOT.indication is decoded as SUBFRAME_INDICATION, and most of the P7 message set is mislabelled the same way. A suite that trusted those labels would be judging the wrong messages.

So CNTC carries its own nFAPI decoder. Message identity is read from the P5 and P7 header bytes against the SCF 222 NR message set, never from an LTE dissector's label. tshark and tcpdump still capture the packets; the decode that the verdict rests on is CNTC's own.

A sequence diagram of the nFAPI split message flow between four participants: the UE running an OAI nr-UE, the PNF at L1 and PHY, the VNF at L2 and L3, and the AMF in a free5GC core. The first phase is nFAPI P5 bring-up over SCTP port 50001, in which the VNF drives the PNF: PNF_PARAM.request, PNF_PARAM.response carrying device capabilities, PNF_CONFIG.request then PNF_START.request, PNF_CONFIG.response then PNF_START.response reaching RUNNING, then PARAM, CONFIG and START.request per PHY instance and their responses with the PHY running. The second phase is the P7 slot loop over UDP ports 50010 and 50011, one exchange per 500 microsecond slot: SLOT.indication carrying SFN and slot, DL_TTI.request with TX_DATA.request, and UL_TTI.request with UL_DCI.request, annotated that no TTI request may be issued for a slot the PHY has already passed. The third phase is UE random access over the rfsimulator: Msg1 PRACH preamble over the air, RACH.indication carrying preamble index and timing advance, DL_TTI.request with TX_DATA.request for the random access response, Msg2 random access response, Msg3 RRCSetupRequest on PUSCH, CRC.indication with RX_DATA.indication, and Msg4 RRCSetup with contention resolution carried in P7. The fourth phase is RRC, NAS and NGAP to the core: RRCSetupComplete with a registration request, InitialUEMessage as NGAP over N2, authentication and security mode command, and registration complete with PDU session establishment.

Testing a PHY without a radio

The obstacle everyone expects with L1 testing is the radio. Certifying a PHY sounds like it needs spectrum, radio hardware, and a signal analyser. The nFAPI wire removes most of that: the P7 loop carries what the PHY reports for every slot, and a software UE over the rfsimulator completes the attach that drives it. This runs on a single Linux box.

What the wire does not carry is what the PHY actually transmitted. TS 38.211 to 38.214 describe the physical layer the PNF implements, and they are deliberately not anchored in the PNF catalog, because this catalog is judged from the nFAPI wire and the nFAPI wire carries what the PNF reports, not the radiated signal. Certifying the physical layer itself needs a radio-side capture this evidence model does not have. Adding those specs to the anchor list would claim a coverage the method cannot deliver, so they are left out and the scorecard states the limit.

What it certifies

A PASS for the PNF asserts that the product, on the stated rig:

  • answers the P5 setup sequence in order, PNF_PARAM then PNF_CONFIG then PNF_START at the device level, and PARAM then CONFIG then START per PHY instance, reaching RUNNING before any P7 traffic (SCF 225 P5, SCF 222 clause 3);
  • runs the P7 slot loop correctly: SLOT.indication every slot, SFN and slot monotonic and wrapping, RACH.indication on preamble detection, CRC.indication and RX_DATA.indication for scheduled uplink (SCF 222);
  • does not crash on malformed input on the P5 or P7 links, confirmed against a control run.

A PASS for the VNF asserts that the product:

  • drives the setup sequence correctly and in order, and issues a CONFIG.request that stays inside the capabilities the PNF advertised in PARAM.response (SCF 225 P5, SCF 222 Table 3-9);
  • issues P7 slot requests ahead of the slot they target, and never for a slot the PHY has already passed (SCF 225 delay management);
  • does not crash on malformed input.

A verdict is only ever issued about what was measured. Requirements that could not be judged on a given deployment are recorded as such, with the reason, and are never promoted to a pass.

Essential and non-essential requirements

Every test carries one field, class: essential or class: normal, and the gate reads only that field. A test is essential when it is a mandatory behaviour of the interface that is observable on the wire and attributable to the node under test, so that a failure breaks interoperability. Three concrete cases:

  • PNF-P5-07, no P7 traffic before START.response, is essential: a PHY that emits slot traffic before it answered START is not in the state it claims, and the peer relies on that state.
  • PNF-P7-06, RACH.indication on preamble, is essential: it is the single message that tells the scheduler a UE is attaching. Without it the RAR is never sent and no UE ever attaches.
  • VNF-P7-05, no TTI request for a slot the PHY has passed, is essential: a request for an elapsed slot is discarded, and on a bridged deployment that is the failure mode that stops a UE attaching.

A test is normal when it is optional in the specification (PNF-P5-08 STOP on teardown), when the outcome is a deployment choice rather than a product fault (PNF-P5-09 P5 on SCTP, reported as observed), or when a single attach cannot reliably exercise it and it would otherwise grade na for no fault of the product (PNF-P7-09 UCI.indication when no PUCCH was scheduled).

How it works

CNTC has two decoupled layers: an engine (ranbench) that measures, and an umbrella (cntc) that judges the serialized results.json against a versioned requirement catalog. Because they are decoupled, any past run can be re-graded without re-running it.

The CNTC RAN FAPI certification pipeline as a seven-segment wheel around a CNTC RAN hub. Stage one, adapter, finds and starts the stack. Stage two, bring up, starts the VNF then the PNF. Stage three, drive, runs one real UE attach. Stage four, capture, tears down and flushes the pcaps. Stage five, decode, also tears down and flushes the pcaps. Stage six, grade, applies a catalog per class. Stage seven, certify, applies the essential gate.

The engine brings the two product classes up in order, runs one UE attach through the whole stack, and tears everything down. The teardown is not cleanup, it is what makes the evidence readable: the stack only closes its capture files at shutdown. The decoded captures then answer the protocol, timing and data path requirements. The robustness requirements are exercised separately, by restarting the products and sending malformed datagrams directly.

ranbench run --config configs/fapi-oai.yaml --target all
  |
  |- acquire the rig lock            one campaign at a time
  |- core preflight                  AMF reachable, subscriber data servable
  |
  |- ONE UE ATTACH
  |    |- VNF up, wait for the P5 listener (SCTP)      [socket]
  |    |- PNF up, wait for the P5 association and P7    [socket]
  |    |- UE attaches, registers, gets a PDU session
  |    |- ping the data network through the UE tunnel
  |    |- stop everything                              [captures flush]
  |
  |- DECODE with the CNTC nFAPI decoder (not tshark labels)
  |- RUN THE SUITE                   the attach cases, plus the robustness cases driven directly
  |- DIAGNOSE any failures
  |- GRADE against the catalog, write scorecard and certificate

A single class takes roughly two to five minutes.

What counts as evidence

Three sources, and nothing else:

EvidenceSourceUsed for
Wire capturethe P5 and P7 pcaps, decoded with the CNTC nFAPI decoderprotocol conformance, timing, the slot loop
Socket statess -an --sctpP5 association, listener readiness
Process statepgrepliveness, crash detection

Product log files are used for diagnosis only, never for a verdict. Sockets and process state cannot be silently stale in the way a log can.

Prerequisites

  • An L1/L2 split under test, deployed by you, with its P5 and P7 packet captures enabled. The reference stacks are pure OAI (two nr-softmodem processes) and the cross-vendor rig (OAI PNF, xFAPI VNF, OCUDU L2 and CU).
  • A 5G core to peer with, providing an AMF for N2 and a UPF for N3. Bring your own: free5GC, Open5GS, OAI-CN5G, SD-Core, or a commercial core. The core is a peer, not the subject of the certificate.
  • A UE simulator. make ran-prereqs builds the OAI nr-UE with its rfsimulator virtual radio, because an L1/L2 stack cannot be exercised without a UE that completes an attach.
  • A Linux host with Python 3.10+, tshark, tcpdump, SCTP support, and passwordless sudo.

Captures are the prerequisite that matters. ranbench reads the wire. A stack that cannot produce P5 and P7 captures can still be checked for liveness and robustness, but its protocol and timing requirements will record na rather than a verdict, and ran-doctor will tell you if capture is off.

Install the framework

git clone https://github.com/TOSSI-Foundation/CNTC.git
cd CNTC
# deps + the OAI UE simulator (uses sudo)
make ran-prereqs

make ran-prereqs builds the UE for the cross-vendor rig by default. For the pure-OAI stack, which also needs the OAI gNB binary, run the bootstrap with the pure-OAI flag:

OAI_GNB=1 ./scripts/bootstrap_ranbench.sh

The OAI nr-UE and nr-softmodem are licensed under the OAI Public License V1.1 by the OpenAirInterface Software Alliance. The script fetches and builds them into your environment; they are not distributed as part of CNTC, which is Apache-2.0, and ranbench invokes them as external processes.

List the product classes and their catalogs with make ran-list:

ranbench, product classes and their CNTC catalogs:
  -- CU/DU split (3GPP TS 33.523) --
  du    O-DU      O-DU (gNB-DU), CNTC Level 1     14 tests,  7 essential, 14 implemented
  cucp  O-CU-CP   O-CU-CP (gNB-CU-CP), Level 1    30 tests, 16 essential, 30 implemented
  cuup  O-CU-UP   O-CU-UP (gNB-CU-UP), Level 1    14 tests,  7 essential, 14 implemented
  -- L1/L2 split over nFAPI (SCF222 / SCF225, not a 3GPP SCAS class) --
  pnf   PNF       PNF (nFAPI L1 / PHY), Level 1   26 tests, 14 essential, 26 implemented
  vnf   VNF       VNF (nFAPI L2 driver), Level 1  15 tests,  9 essential, 15 implemented

Configure your stack

Describe the stack under test in a campaign config. Two are provided, configs/fapi-oai.yaml for the pure-OAI stack and configs/fapi-split.yaml for the cross-vendor stack. Copy one and change the paths and cell parameters for your host.

The key fields are:

  • ran.adapter, the plugin. fapi_oai for the pure-OAI stack, fapi_split for the cross-vendor stack.
  • ran.procs, one block per process. The pure-OAI config has vnf and pnf; the cross-vendor config adds cu and l2. Each block sets the binary, its arguments, and the process name pgrep will find.
  • ran.nfapi_ports, the P5 and P7 endpoints. The VNF listens on p5_vnf (SCTP) and the PNF dials it; P7 is UDP. Defaults are p5_pnf: 50000, p5_vnf: 50001, p7_pnf: 50010, p7_vnf: 50011.
  • core.adapter, the core peer. Use manual for any core you manage yourself, or free5gc_k8s for optional convenience helpers.
  • drivers.ue_*, the UE binary and its radio parameters, which must agree with the cell the L2 broadcasts.
  • knobs.*.radio, set to simulated on an rfsimulator rig, which grades slot cadence and jitter na because the sample clock, not the PHY, sets the rate. Set it to hardware to grade those on a real radio.

Confirm the rig is ready before spending a run:

make ran-oai-fapi-doctor

or, for either stack:

make ran-doctor CONFIG=configs/fapi-oai.yaml

A ready rig prints:

ranbench doctor, ran=fapi_oai  target=all
  [ok  ] cli:tshark       /usr/bin/tshark
  [ok  ] ran:build        L1/L2 split over nFAPI (pure OAI), built: vnf, pnf
  [ok  ] ep:pnf           127.0.0.1:50010
  [ok  ] pcap:pnf         p5, p7
  [ok  ] ep:vnf           127.0.0.1:50011
  [ok  ] pcap:vnf         p5, p7
  [ok  ] rfsim port       free for the PNF to bind
  [ok  ] core             free5gc_k8s (N2/N3 peer)
  [ok  ] subscribers      1 in the campaign config
  [ok  ] amf n2           10.43.24.185:38412 accepting SCTP
  [ok  ] subscriber data  UDM serves sm-data for imsi-208930000000001

  RESULT: READY

The last two checks contact the core rather than trusting the config. Both catch failures that otherwise look like stack faults: an unreachable AMF stops the attach at NG Setup, and a core that cannot serve subscription data lets registration succeed and then refuses the PDU session.

Run the certification

Reset the AMF before every run, then run. Certify one product class at a time:

make ran-oai-fapi-run TARGET=pnf CAMPAIGN=MY-NFAPI-PNF
make ran-oai-fapi-run TARGET=vnf CAMPAIGN=MY-NFAPI-VNF

Or grade both in one run, which produces the two scorecards plus a composite verdict:

make ran-oai-fapi-run TARGET=all CAMPAIGN=MY-NFAPI-001

For the cross-vendor stack, use the generic target with the other config:

make ran-run CONFIG=configs/fapi-split.yaml TARGET=all CAMPAIGN=MY-XFAPI-001

split: fapi in the config makes --target all expand to pnf and vnf only. The run starts and stops every process itself, in the required order, so stop any stack you brought up by hand first. One campaign per rig: a run owns the stack, and two at once tear down each other's processes mid-attach. A second concurrent run is refused.

Read the verdict and scorecard

Every run writes campaigns/<id>/scorecard-pnf.md, scorecard-vnf.md, and a composite scorecard.md, plus the same in HTML.

====================================================================
CNTC VERDICT, profile: vnf-conformance  (catalog v1.0.0)
VNF (nFAPI L2 driver), CNTC Level 1
====================================================================

 [PASS] * VNF-P5-01   PNF_PARAM.request issued to discover capabilities   status == pass
 [PASS] * VNF-P5-04   PARAM, CONFIG then START issued in order            status == pass
 [PASS] * VNF-P5-05   CONFIG stays inside the advertised capabilities     status == pass
 [ na ]   VNF-P7-01   DL_TTI.request ahead of its slot                    na: host descheduled the stack
 [PASS] * VNF-NEG-01  Malformed nFAPI datagram, no VNF crash              status == pass

 essential gate (all): 6 passed / 0 failed / 3 na  (of 9)

RESULT:  INCOMPLETE

Three outcomes, and the third is the important one:

  • PASS, every essential requirement was exercised and met.
  • FAIL, an essential requirement was exercised and not met.
  • INCOMPLETE, an essential requirement could not be judged. It is never silently promoted to a pass.

The na outcome on this split

na is not a hedge. It records that the evidence needed to judge a requirement was not obtained on this deployment, and it names what would be needed. The L1/L2 split produces more na than the CU/DU split does, for reasons that are all real and all attributable to the rig rather than the product. Four examples from the reference run:

  • Slot cadence under a radio simulator. PNF-P7-01 and PNF-TIME-01 grade na because the rfsimulator sample clock, not the PHY, sets the slot rate. On a real radio they are judgeable. The scorecard reports the measured rate anyway so the number is not lost.
  • VNF slot timing on a shared host. VNF-P7-01, VNF-P7-02 and VNF-P7-05 grade na when the SLOT.indication stream shows the host descheduled the stack. A late request cannot be blamed on the VNF when the whole process was stalled by the operating system. On a CPU-isolated, pinned rig or a real radio they are judgeable.
  • A message a compliant peer need not send. PNF-P5-08 (STOP) and PNF-ERR-01 (ERROR.indication) grade na because the attach stimulus does not trigger them. Their absence is not a fault.
  • Transport protection on loopback. PNF-SEC-01 and VNF-SEC-01 grade na because P5 and P7 run between loopback addresses on a single-host rig, so their transport is neither exercised nor observable. SCF 225 defines no security for nFAPI, so this states a deployment fact, not a spec violation.

Most test tools would have reported the timing cases as failures against the product. None of them is a defect. Reporting them honestly is the point of the framework.

The certificate

A certificate is issued automatically only when every essential requirement passes:

# PASS only
make ran-certify CAMPAIGN=MY-NFAPI-VNF TARGET=vnf

It records the profile, the catalog version, the standards covered, and the essential-gate result, so it is auditable against the campaign that produced it. A run that fails or cannot judge an essential requirement yields no certificate.

Every campaign keeps its captures and the product logs under campaigns/<id>/raw/, so any finding can be re-checked against the evidence it was drawn from. That is the difference between a report and a certification: anyone can verify the claim themselves.

Live dashboard

# http://<host>:8050   (or: make dashboard-bg to run detached)
make dashboard

The dashboard renders every campaign: the product classes with their verdicts, per-test cards with the decoded evidence, the problems found, and the certificate. Each card separates what was observed, which decided the verdict, from the probable cause, which is inferred and tells you where to look.

Verified results

The framework was run against the pure-OAI stack, two nr-softmodem processes on one host peered with free5GC on Kubernetes, driven by an OAI nr-UE over the rfsimulator. All 41 requirements execute, and the run is repeatable: two consecutive campaigns produced identical verdicts.

Product classTestspassfailnaVerdict
PNF261817FAIL, essential 12/1/1
VNF15915INCOMPLETE, essential 6/0/3

The PNF fails one essential requirement, PNF-P5-07. The VNF passes every essential requirement it could judge and grades INCOMPLETE only because three timing requirements went na on this shared host, for the reason given above. Its one non-essential fail, VNF-SYNC-01, is that it did not issue DL_NODE_SYNC, which is why the matching PNF-SYNC-01 reads na: the PNF was never asked to answer. The two halves agree, read from opposite directions of the same wire.

Finding: P7 traffic before the PHY reports running

The PNF emits P7 slot traffic before it has answered START.response. The SCF state order is IDLE then CONFIGURED then RUNNING, and P7 belongs only to RUNNING. On the reference PHY, the first slot traffic appears 48 ms before the START handshake completes.

This is not a broken PHY. The attach still completes. It is specifically a state-machine ordering violation: for that 48 ms window the PHY is emitting traffic in a state it has not yet declared, and a VNF that trusted the declared state would act on it. It is caught by PNF-P5-07, and because the PNF binary is identical in both stacks, the same finding appears on the cross-vendor rig, which is a useful confirmation that the finding is in the L1 and not the harness.

The physical layer itself is not judged, because the nFAPI wire carries what the PHY reports, not what it transmitted, and slot cadence and jitter record na under a simulator because the sample clock sets the rate. A test that cannot be judged records na with the reason, never a pass.

Supported stacks and cores

One adapter per stack keeps them comparable. An adapter implements a small contract: describe, endpoint, liveness, start, stop, capture paths. The 41 test cases and the grading layer do not change, because they work on the decoded nFAPI capture and socket state rather than anything stack-specific.

StackSplitState
pure OAI (two nr-softmodem)Option 6, nFAPIvalidated end to end
cross-vendor (OAI PNF, xFAPI VNF, OCUDU L2)Option 6, nFAPIvalidated end to end
other nFAPI PNF or VNF productsOption 6, nFAPIadd an adapter

For the core, any 5G core works. Set core.adapter: manual and ranbench will not probe or modify it; you confirm it is up with the SIM provisioned. A free5gc_k8s adapter adds optional convenience helpers.

Troubleshooting

  • ran-doctor reports no pcaps. The P5 or P7 capture is off. Enable it in the process config. Without it, protocol and timing requirements can only record na.
  • rfsim port ... HELD. Something already owns the rfsimulator port, often a stray gNB. The PNF cannot bind it and no UE synchronises. Free the port before running.
  • UE reaches RRC_CONNECTED then stops, or Duplicated PDU session ID in the core. The core is holding stale state. Reset the AMF before each campaign, and the SMF and UPF if the UPF has dropped its PFCP association.
  • Registration succeeds but the PDU session is refused. This is a core fault, not a stack fault. ran-doctor makes the same subscription-data request the SMF makes and reports it.
  • STIMULUS INCOMPLETE in the run banner. The attach did not finish, so requirements past the break recorded na. The banner names the root fault, quoted from the product's own log. The verdict is void; fix the rig and re-run.
  • A second run is refused. Another campaign is driving the rig. Runs cannot overlap.

What is coming

nFAPI Split Certification today certifies the L1/L2 split at Level 1. The framework was built so that each extension adds catalogs and adapters rather than changing the grading core.

  • O-RAN Open Fronthaul, the O-DU to O-RU boundary. Split Option 7.2x with its Control, User, Sync and Management planes is the next split down. Certifying an O-RU against its O-DU, and the fronthaul itself, extends the same model one more layer, against the O-RAN ALLIANCE interoperability and security specifications.
  • More nFAPI products. The stack-specific code is confined to one adapter. Support for other open-source and commercial PNF and VNF products is a matter of adding adapters, and an adapter is the smallest useful contribution anyone can make.
  • Level 2, adversarial robustness. Level 1 asks whether the product does the right thing when its peer behaves. Level 2 asks what it does when the peer sends a message in the wrong state, a configuration outside the advertised capabilities, or a slot request timed to fall in the gap. These need a deliberately misbehaving peer to drive them.
  • Performance and scale. Level 1 asks whether the split is correct, not how much it can carry. Slot timing budget under load, and the rate at which the P7 loop stays inside it, is the natural next axis.

Standards and references

Interface specifications

SpecificationCovers
Small Cell Forum SCF 2225G FAPI, PHY API Specification, 10th edition (July 2025): the P5 configuration and P7 slot messages and procedures, the MAC to PHY interface
Small Cell Forum SCF 2255G nFAPI: the network transport wrapper around SCF 222, forming the Split Option 6 interface between the L2 and L1

Specifications referenced by individual requirements

SpecificationCovers
3GPP TS 38.321NR Medium Access Control, the ra-ResponseWindow that PNF-TIME-02 measures the RACH.indication against
3GPP TR 38.801Study on new radio access technology, the eight functional split options, Option 6
3GPP TS 38.401NG-RAN architecture

Specifications not used as anchors

SpecificationWhy
3GPP TS 38.211 to 38.214The physical layer the PNF implements. Not anchored, because the nFAPI wire carries what the PNF reports, not the radiated signal, and certifying the PHY itself needs a radio-side capture this evidence model does not have.

Specifications for the roadmap

SpecificationCovers
O-RAN.WG4Open Fronthaul: Control, User and Sync plane, and Management plane
O-RAN.WG11Security requirements and protocols for O-RAN interfaces

Software under test and tooling

ProjectRoleLicense
OpenAirInterface nr-softmodemThe PNF and, on the pure-OAI stack, the VNFOAI Public License V1.1
xFAPIThe VNF on the cross-vendor stackvendor-supplied
OCUDUThe L2 and CU on the cross-vendor stackBSD-3-Clause-Open-MPI
OpenAirInterface nr-UEUE simulator, the stimulusOAI Public License V1.1
free5GC5G core peer used in validationApache-2.0
Wireshark / tsharkPacket capture (decode is CNTC's own)GPL-2.0-or-later
CNTCThis frameworkApache-2.0

CNTC is a project of the TOSSI Foundation. nFAPI Split Certification is part of Stage 3, alongside the CU/DU Split, after UPF Certification (Stage 1) and 5G Core Control Plane Certification (Stage 2).