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 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.
| Split | Interface | Separates | CNTC |
|---|---|---|---|
| Option 2 | F1 | CU from DU | CU/DU Split |
| Option 2 (control/user) | E1 | CU-CP from CU-UP | CU/DU Split |
| Option 6 | FAPI, nFAPI | L2 from L1, MAC from PHY | this document |
| Option 7.2x | Open Fronthaul | O-DU from O-RU | roadmap |
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 class | SCF role | What it is | Messages driven | Tests |
|---|---|---|---|---|
| PNF | Physical Network Function | the L1/PHY end | answers P5 setup, drives the P7 slot loop | 26 (14 essential) |
| VNF | Virtual Network Function | the L2 end that terminates nFAPI northbound of the PNF | issues the P5 setup, issues the P7 slot requests | 15 (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.
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 PNF | OAI nr-softmodem --nfapi PNF (same binary) |
| VNF | OAI nr-softmodem --nfapi VNF (carries L2 and L3) | xFAPI, in front of an OCUDU L2 |
| CU | none: the VNF terminates N2/N3 itself | OCUDU CU over F1 |
| processes | two (VNF, PNF) | four (CU, VNF, PNF, L2) |
| adapter | fapi_oai (subclasses fapi_split) | fapi_split |
| build | OAI_GNB=1 ./scripts/bootstrap_ranbench.sh | FAPI=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.
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_PARAMthenPNF_CONFIGthenPNF_STARTat the device level, andPARAMthenCONFIGthenSTARTper PHY instance, reaching RUNNING before any P7 traffic (SCF 225 P5, SCF 222 clause 3); - runs the P7 slot loop correctly:
SLOT.indicationevery slot, SFN and slot monotonic and wrapping,RACH.indicationon preamble detection,CRC.indicationandRX_DATA.indicationfor 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.requestthat stays inside the capabilities the PNF advertised inPARAM.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 beforeSTART.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.indicationon 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 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:
| Evidence | Source | Used for |
|---|---|---|
| Wire capture | the P5 and P7 pcaps, decoded with the CNTC nFAPI decoder | protocol conformance, timing, the slot loop |
| Socket state | ss -an --sctp | P5 association, listener readiness |
| Process state | pgrep | liveness, 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-softmodemprocesses) 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-prereqsbuilds 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_oaifor the pure-OAI stack,fapi_splitfor the cross-vendor stack.ran.procs, one block per process. The pure-OAI config hasvnfandpnf; the cross-vendor config addscuandl2. Each block sets the binary, its arguments, and the process namepgrepwill find.ran.nfapi_ports, the P5 and P7 endpoints. The VNF listens onp5_vnf(SCTP) and the PNF dials it; P7 is UDP. Defaults arep5_pnf: 50000,p5_vnf: 50001,p7_pnf: 50010,p7_vnf: 50011.core.adapter, the core peer. Usemanualfor any core you manage yourself, orfree5gc_k8sfor optional convenience helpers.drivers.ue_*, the UE binary and its radio parameters, which must agree with the cell the L2 broadcasts.knobs.*.radio, set tosimulatedon an rfsimulator rig, which grades slot cadence and jitternabecause the sample clock, not the PHY, sets the rate. Set it tohardwareto 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-01andPNF-TIME-01gradenabecause 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-02andVNF-P7-05gradenawhen theSLOT.indicationstream 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) andPNF-ERR-01(ERROR.indication) gradenabecause the attach stimulus does not trigger them. Their absence is not a fault. - Transport protection on loopback.
PNF-SEC-01andVNF-SEC-01gradenabecause 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 class | Tests | pass | fail | na | Verdict |
|---|---|---|---|---|---|
| PNF | 26 | 18 | 1 | 7 | FAIL, essential 12/1/1 |
| VNF | 15 | 9 | 1 | 5 | INCOMPLETE, 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.
| Stack | Split | State |
|---|---|---|
| pure OAI (two nr-softmodem) | Option 6, nFAPI | validated end to end |
| cross-vendor (OAI PNF, xFAPI VNF, OCUDU L2) | Option 6, nFAPI | validated end to end |
| other nFAPI PNF or VNF products | Option 6, nFAPI | add 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-doctorreports no pcaps. The P5 or P7 capture is off. Enable it in the process config. Without it, protocol and timing requirements can only recordna.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 IDin 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-doctormakes the same subscription-data request the SMF makes and reports it. STIMULUS INCOMPLETEin the run banner. The attach did not finish, so requirements past the break recordedna. 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
| Specification | Covers |
|---|---|
| Small Cell Forum SCF 222 | 5G 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 225 | 5G nFAPI: the network transport wrapper around SCF 222, forming the Split Option 6 interface between the L2 and L1 |
Specifications referenced by individual requirements
| Specification | Covers |
|---|---|
| 3GPP TS 38.321 | NR Medium Access Control, the ra-ResponseWindow that PNF-TIME-02 measures the RACH.indication against |
| 3GPP TR 38.801 | Study on new radio access technology, the eight functional split options, Option 6 |
| 3GPP TS 38.401 | NG-RAN architecture |
Specifications not used as anchors
| Specification | Why |
|---|---|
| 3GPP TS 38.211 to 38.214 | The 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
| Specification | Covers |
|---|---|
| O-RAN.WG4 | Open Fronthaul: Control, User and Sync plane, and Management plane |
| O-RAN.WG11 | Security requirements and protocols for O-RAN interfaces |
Software under test and tooling
| Project | Role | License |
|---|---|---|
| OpenAirInterface nr-softmodem | The PNF and, on the pure-OAI stack, the VNF | OAI Public License V1.1 |
| xFAPI | The VNF on the cross-vendor stack | vendor-supplied |
| OCUDU | The L2 and CU on the cross-vendor stack | BSD-3-Clause-Open-MPI |
| OpenAirInterface nr-UE | UE simulator, the stimulus | OAI Public License V1.1 |
| free5GC | 5G core peer used in validation | Apache-2.0 |
| Wireshark / tshark | Packet capture (decode is CNTC's own) | GPL-2.0-or-later |
| CNTC | This framework | Apache-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).