F1AP interface architecture
14 minute read
Target audience: RAN engineers. Scope: the F1AP (F1-C) interface implementation in OCUDU — class ownership on both gNB-CU and gNB-DU sides, procedure layout, per-procedure flows (interface mgmt, UE context, RRC transfer, paging, positioning), and how F1AP integrates with CU-CP and DU-Manager. Reference: 3GPP TS 38.473. F1-U (NR-U user-plane) is data-plane and lives separately under lib/f1u/ — out of scope for this doc.
1. What F1AP Is in OCUDU
F1AP is the control-plane protocol between the gNB-CU and gNB-DU, carried over SCTP on the F1-C reference point. OCUDU implements both ends of F1AP from a single set of ASN.1 types (asn1::f1ap) but with two distinct top-level classes: f1ap_cu_impl on the CU-CP side (lib/f1ap/cu_cp/) and f1ap_du_impl on the DU side (lib/f1ap/du/). Common code (ASN.1 helpers, error-indication helpers, message structs) lives in lib/f1ap/common/ and at the lib/f1ap/ root.
Three design rules shape the module:
- Symmetric coroutine procedure framework on both sides. Every request-response exchange — F1 Setup, UE Context Setup/Modify/Release, gNB-CU/DU Configuration Update, F1 Removal, Positioning — is an
async_task<R>under aprocedures/subdirectory of either side. Non-transaction messages (DL/UL RRC Message Transfer, Initial UL RRC, Paging, Error Indication, Access Success, UE Context Release Request, UE Context Modification Required) are direct-dispatch handlers in the impl class. - Two F1AP UE IDs, one allocated by each side. The DU allocates
gNB-DU-UE-F1AP-IDwhen the UE first appears (Initial UL RRC Message Transfer) by simple sequential increment. The CU allocatesgNB-CU-UE-F1AP-IDwhen it receives that Initial UL RRC and accepts the UE. From that point on, every UE-associated F1AP message carries both IDs. - Adapter handoff to the parent layer. Neither F1AP impl reaches into RRC, CU-CP UE manager, or DU-Manager directly. The CU side calls
f1ap_du_processor_notifier; the DU side callsf1ap_du_configurator. Each is implemented by the parent layer to orchestrate everything else (RRC context creation, MAC/RLC bring-up, bearer setup, UE removal).
2. Module Ownership Graph
2.1 CU side
f1ap_cu_impl (lib/f1ap/cu_cp/f1ap_cu_impl.h) is constructed with (f1ap_configuration, f1ap_message_notifier& tx, f1ap_du_processor_notifier&, timer_manager&, task_executor& ctrl_exec). Key state: f1ap_du_context du_ctxt (gnb_du_id_t, du_name), f1ap_ue_context_list ue_ctxt_list with sequential gnb_cu_ue_f1ap_id allocator (hole-filling on dealloc), and f1ap_event_manager ev_mng carrying the global protocol_transaction_manager<f1ap_transaction_response> sized for 256 concurrent transactions (matches the uint8 transaction-ID range).
Per-UE state — f1ap_ue_context (lib/f1ap/cu_cp/ue_context/f1ap_cu_ue_context.h):
struct f1ap_ue_ids { ue_index_t ue_index; gnb_cu_ue_f1ap_id_t cu_id; std::optional<gnb_du_ue_f1ap_id_t> du_id; };
struct f1ap_ue_context {
f1ap_ue_ids ue_ids;
bool marked_for_release;
manual_event<ue_index_t> release_complete_event;
f1ap_ue_transaction_manager ev_mng; // per-UE event sources
ue_ul_bearer_manager bearer_manager; // SRB0/1/2 UL forwarders
f1ap_ue_logger logger;
};
The per-UE transaction manager carries event sources for context_setup_outcome, context_modification_outcome, context_release_complete, positioning_information_outcome, and positioning_activation_outcome. A coroutine procedure subscribes a protocol_transaction_outcome_observer (the transaction_sink) to the relevant source; the inbound message handler sets the source when the matching response arrives.
2.2 DU side
f1ap_du_impl (lib/f1ap/du/f1ap_du_impl.h) is constructed with (f1c_connection_client&, f1ap_du_configurator&, task_executor& ctrl_exec, f1ap_ue_executor_mapper&, f1ap_du_paging_notifier&, timer_manager&). State: f1ap_du_context ctxt (gnb_du_id, gnb_du_name, f1c_setup flag, slotted_id_vector<du_cell_index_t, f1ap_du_cell_context> served_cells), f1ap_du_ue_manager ues allocating gnb_du_ue_f1ap_id_t by simple next_gnb_f1ap_du_ue_id++ increment, f1ap_du_connection_handler connection_handler for TNL lifecycle, and std::unique_ptr<f1ap_event_manager> events carrying the global transaction manager.
Per-UE state — f1ap_du_ue (lib/f1ap/du/ue_context/f1ap_du_ue.h) holds (ue_index, gnb_du_ue_f1ap_id, optional<gnb_cu_ue_f1ap_id>), an explicit ue_rrc_state enum (no_config / config_pending / configured) used to gate when SRBs become forwardable, and a f1c_bearer_manager bearers for SRB/DRB F1-C bearer state.
3. Interface Management Procedures (TS 38.473 §8.2)
sequenceDiagram
autonumber
participant DUMGR as du_manager
participant FDU as f1ap_du_impl
participant FCU as f1ap_cu_impl
participant DUPROC as du_processor (CU-CP)
Note over DUMGR,DUPROC: F1 Setup (DU-initiated, §8.2.3)
DUMGR->>FDU: handle_f1_setup_request(request)
FDU->>FCU: F1SetupRequest (gNB-DU-ID · served cells · PLMN/S-NSSAI)
alt Success
FCU->>DUPROC: on_f1_setup_request(...)
DUPROC-->>FCU: response
FCU-->>FDU: F1SetupResponse (gNB-CU name · cells to activate)
FDU->>FDU: ctxt.f1c_setup = true
else Failure with time_to_wait
FCU-->>FDU: F1SetupFailure (time_to_wait)
FDU->>FDU: backoff via f1_setup_wait_timer · retry
end
FDU-->>DUMGR: f1_setup_resultF1 Setup (§8.2.3) — DU-initiated. CU side: lib/f1ap/cu_cp/procedures/f1_setup_procedure.h. DU side: lib/f1ap/du/procedures/f1ap_du_setup_procedure.{h,cpp}, class f1ap_du_setup_procedure, coroutine returning async_task<f1_setup_result>. The DU sends F1SetupRequest (gNB-DU-ID, served cells with NR-CGI, supported PLMNs, S-NSSAIs, gNB-DU name) and awaits. On F1SetupFailure carrying a time_to_wait IE, an internal unique_timer f1_setup_wait_timer backs off and the procedure retries with an incremented f1_setup_retry_no. On success, f1ap_du_context.f1c_setup is set and the served-cells list becomes the canonical record. This procedure is the precondition for every UE-associated message on the link.
gNB-DU Configuration Update (§8.2.4) — DU-initiated, post-Setup. lib/f1ap/du/procedures/f1ap_du_gnbdu_config_update_procedure.h. Coroutine async_task<gnbdu_config_update_response>. Triggered by du_manager when the served-cell set changes (cell add/modify/remove). The CU receives via f1ap_cu_impl::handle_du_config_update().
gNB-CU Configuration Update (§8.2.5) — CU-initiated. CU side: lib/f1ap/cu_cp/procedures/gnb_cu_configuration_update_procedure.h, class gnb_cu_configuration_update_procedure, coroutine async_task<f1ap_gnb_cu_configuration_update_response>. DU side: lib/f1ap/du/procedures/gnb_cu_configuration_update_procedure.h. On the DU, dispatch goes through the control executor to the procedure; the response outcome event lives in the global event manager.
Reset (§8.2.1) — bidirectional. DU receiving CU-initiated reset: lib/f1ap/du/procedures/f1ap_du_reset_procedure.h, class reset_procedure, coroutine async_task<void>. Supports both the full reset form (empty UE list — reset all) and partial reset (per-UE list of gnb_du_ue_f1ap_id / gnb_cu_ue_f1ap_id pairs). The procedure iterates ues to find the matching UEs, calls du_mng.request_reset(ues_to_reset) async, and emits RESET ACK carrying the released UE-associated F1-connections list. DU-initiated reset is symmetrically implemented in f1ap_du_initiated_reset_procedure.h.
Error Indication (§8.2.2) — bidirectional. Helper generate_error_indication(transaction_id, du_ue_id, cu_ue_id, cause) in lib/f1ap/f1ap_common_messages.h. The DU side calls it via f1ap_du_impl::send_error_indication() for the standard cases — unknown / inconsistent UE F1AP IDs, unknown or already-allocated gnb_cu_ue_f1ap_id. Can be UE-associated (both UE IDs present) or non-UE-associated.
F1 Removal (§8.2.8) — CU-initiated graceful disconnect. CU side: lib/f1ap/cu_cp/procedures/f1_removal_procedure.h. DU side: lib/f1ap/du/procedures/f1ap_du_removal_procedure.h, class f1ap_du_removal_procedure, coroutine async_task<void>. The DU sends F1 Removal Response, then triggers connection_handler.handle_tnl_association_removal() to close the SCTP association; on failure the TNL is force-closed. TNL teardown invokes du_mng.request_reset() for all UEs.
gNB-DU Resource Coordination (§8.2.6) — not implemented (no procedure file present; the res_coordination_transfer_info IE appears in UE context types but has no dedicated procedure).
4. UE Context Management Procedures (TS 38.473 §8.3)
sequenceDiagram
autonumber
participant UE
participant DU as f1ap_du_impl
participant CU as f1ap_cu_impl
participant RRC as RRC / CU-CP
Note over UE,RRC: Initial attach (§8.4.1 + §8.3.2)
UE->>DU: RRC Setup Request on SRB0
DU->>DU: allocate gnb_du_ue_f1ap_id
DU->>CU: InitialULRRCMessageTransfer (DU-UE-F1AP-ID · NR-CGI · C-RNTI · DU-to-CU container)
CU->>CU: allocate gnb_cu_ue_f1ap_id
CU->>RRC: on_ue_rrc_context_creation_request
RRC-->>CU: rrc context created
Note over CU: ue_ctxt_list.add_ue(ue_index, cu_ue_f1ap_id)
CU->>DU: UEContextSetupRequest (SRBs · DRBs · MAC/RLC config)
DU->>DU: du_mng.request_ue_creation()
DU-->>CU: UEContextSetupResponse (DU-UE-F1AP-ID · C-RNTI)Initial UL RRC Message Transfer (§8.4.1) — DU → CU, the entry point for any new UE. CU handler: f1ap_cu_impl::handle_initial_ul_rrc_message() (lib/f1ap/cu_cp/f1ap_cu_impl.cpp, lines 309–409). The CU allocates a fresh gnb_cu_ue_f1ap_id, calls du_processor_notifier.on_ue_rrc_context_creation_request(req) which the CU-CP fulfils by creating the RRC UE context, then either creates a new F1AP UE context (ue_ctxt_list.add_ue(ue_index, cu_ue_f1ap_id)) or — for an RRC reestablishment-on-same-DU case — updates the existing context with the new gnb_du_ue_f1ap_id. Finally it registers SRB0/1/2 UL bearer notifiers and forwards the embedded RRC PDU to the RRC entity.
UE Context Setup (§8.3.2) — CU-initiated, the procedure that materializes everything on the DU. CU side: lib/f1ap/cu_cp/procedures/ue_context_setup_procedure.h, class ue_context_setup_procedure, coroutine async_task<f1ap_ue_context_setup_response>. The procedure (a) finds-or-creates the F1AP UE context, (b) sends UEContextSetupRequest to the DU, (c) awaits via the per-UE transaction_sink typed protocol_transaction_outcome_observer<ue_context_setup_resp_s, ue_context_setup_fail_s>, (d) on success creates the RRC context. DU side: lib/f1ap/du/procedures/f1ap_du_ue_context_setup_procedure.h. The DU schedules the procedure on the per-UE executor through du_mng.get_ue_handler(du_ue_index).schedule_async_task(...). Materialized state: SRBs activated as F1-C bearers, DRBs created via du_mng.request_ue_context_update() (which spins up RLC/MAC), optional SCells, optional measurement config, optional DRX. The two UE IDs are bound at this point: CU-UE-F1AP-ID is in the request; DU-UE-F1AP-ID flies back in the response.
UE Context Modification (§8.3.4) — CU-initiated, used for DRB add/modify/release and serving-cell reconfigurations. CU side: lib/f1ap/cu_cp/procedures/ue_context_modification_procedure.h, coroutine async_task<f1ap_ue_context_modification_response>. DU side: lib/f1ap/du/procedures/f1ap_du_ue_context_modification_procedure.h. On the DU, the impl looks up the UE by gnb_du_ue_f1ap_id and dispatches to the per-UE handler.
UE Context Release (§8.3.5) — CU-initiated. CU side: lib/f1ap/cu_cp/procedures/ue_context_release_procedure.h, coroutine async_task<ue_index_t> (returns the released UE index). The Release Command optionally carries the RRC Release PDU to deliver over Uu before teardown. DU side: lib/f1ap/du/procedures/f1ap_du_ue_context_release_procedure.h. The DU impl handles a special case where the command carries an old gnb_du_ue_f1ap_id (from RRC reestablishment) — that old context is scheduled for removal first. The procedure ends in du_mng.request_ue_removal().
UE Context Release Request (§8.3.6) — DU-initiated, sent when the DU detects RLF (RLC or MAC), cell unavailability, or another local fault and wants the CU to release the UE. DU handler: f1ap_du_impl::handle_ue_context_release_request(). CU handler: f1ap_cu_impl::handle_ue_context_release_request(). No transaction ID — the CU acts by initiating its own ue_context_release_procedure.
UE Context Modification Required (§8.3.7) — DU-initiated, the DU asks the CU to reduce/modify the UE’s resource configuration (e.g. resource shortage). DU handler: f1ap_du_impl::handle_ue_context_modification_required(), coroutine async_task<f1ap_ue_context_modification_confirm>, awaits events->f1ap_ue_context_modification_outcome.
Access Success (§8.3.9) — Conditional Handover related, DU notifies CU when a CHO target UE successfully accesses. DU handler: f1ap_du_impl::handle_access_success(). CU handler: f1ap_cu_impl::handle_access_success(). The CU forwards to the mobility manager via du_processor_notifier.on_access_success().
UE Inactivity Notification (§8.3.8) — not implemented. The DU handler handle_ue_inactivity_notification() is a no-op ({}).
Notify (§8.3.7 — RAN-initiated notify) — not implemented. handle_notify() is a no-op.
5. RRC Message Transfer (TS 38.473 §8.4)
DL RRC Message Transfer (§8.4.2) — CU → DU, then over Uu via the indicated SRB. CU sender: f1ap_cu_impl::handle_dl_rrc_message_transfer(). The CU may include oldgNB-DU-UE-F1AP-ID (when this delivery follows an RRC reestablishment, taken from ue_ctxt.pending_old_ue_id set by handle_ue_id_update()) and/or a new gnb_cu_ue_f1ap_id per TS 38.473 §8.4.2.2. DU receiver: f1ap_du_impl::handle_dl_rrc_message_transfer() (f1ap_du_impl.cpp, lines 222–293) — looks up the UE by gnb_du_ue_f1ap_id, handles the old-UE case (marks the old context for release without running the full Release procedure, deletes its gnb_cu_ue_f1ap_id so the old UE becomes unreachable, calls du_mng.notify_reestablishment_of_old_ue()), promotes the UE’s rrc_state from no_config to config_pending if needed, then resolves the SRB by ID and forwards the PDU. The optional rrc_delivery_status_request_present IE is honored.
UL RRC Message Transfer (§8.4.3) — DU → CU. Initiating message. CU receiver: f1ap_cu_impl::handle_ul_rrc_message() looks up the UE by gnb_cu_ue_f1ap_id, validates that SRB0 is not used for UL (SRB0 is initial-only — UL on it is an error), and routes to the SRB1 or SRB2 notifier.
RRC Delivery Report (§8.4.4) — not implemented. DU handler handle_rrc_delivery_report() is a no-op.
6. Paging (TS 38.473 §8.5)
CU sender: f1ap_cu_impl::handle_paging() packs the F1AP Paging PDU via fill_asn1_paging_message() and sends it. DU receiver: handle_paging_request() in lib/f1ap/du/procedures/f1ap_du_paging_procedure.h — function signature bool handle_paging_request(const asn1::f1ap::paging_s&, f1ap_du_paging_notifier&, f1ap_du_context&, ocudulog::basic_logger&). The Paging IE includes optional cell-list (pagingCell per the TS 38.304 paging mechanism) and a UE paging ID list; the DU forwards each paging item to the per-cell paging scheduler via f1ap_du_paging_notifier.
7. Positioning (TS 38.473 §8.13)
NRPPa-related procedures are fully implemented in F1AP. Each has a CU-initiated procedure class and a matching DU-side handler.
| Procedure | TS § | CU-side procedure | DU-side handler |
|---|---|---|---|
| Positioning Information Exchange | §8.13.9 | f1ap_positioning_information_exchange_procedure.h | f1ap_du_positioning_information_exchange_procedure.h |
| Positioning Activation | §8.13.10 | f1ap_positioning_activation_procedure.h | (CU-initiated only — no dedicated DU file found) |
| Positioning Measurement | §8.13.3 | f1ap_positioning_measurement_procedure.h | f1ap_du_positioning_measurement_procedure.h |
| TRP Information Exchange | §8.13.8 | f1ap_trp_information_exchange_procedure.h | f1ap_du_trp_information_exchange_procedure.h |
CU-side procedures are coroutines returning async_task<expected<response, failure>> and use per-UE event sources positioning_information_outcome / positioning_activation_outcome for correlation.
8. Warning, Trace, System Information
- Warning Messages (§8.7) — not implemented (no procedure files; no
write/replace/kill warninghandlers found). - Trace (§8.8) — not implemented (no trace start / deactivate / failure procedure files).
- System Information delivery (§8.6) — no F1AP procedures found. The DU’s setup procedure contains a comment about cell-side System Information being added autonomously; SI delivery in OCUDU is not done over F1AP procedure 8.6 today.
9. Procedure Framework
Both sides share the same coroutine shape used elsewhere in OCUDU. A typical CU-initiated procedure looks like:
void operator()(coro_context<async_task<R>>& ctx) {
CORO_BEGIN(ctx);
if (!find_or_create_f1ap_ue_context()) { CORO_EARLY_RETURN(failure); }
send_request(); // packs ASN.1 and dispatches to tx notifier
CORO_AWAIT_VALUE(response, transaction_sink); // suspend until matching outcome arrives
if (response.has_value()) { /* success path */ }
else { /* failure path */ }
CORO_RETURN(result);
}
transaction_sink is a protocol_transaction_outcome_observer<SuccessfulOutcomeT, UnsuccessfulOutcomeT> subscribed either to a per-UE event source (in f1ap_ue_transaction_manager) for UE-associated procedures, or to a global event source (in f1ap_event_manager) for non-UE-associated ones. The transaction ID — a uint8_t in the range 0–255 — is allocated by ev_mng.transactions.create_transaction() and stamped into the ASN.1 PDU; the inbound message dispatcher resolves the response by calling set_response(transaction_id, ...).
Per-transaction timers are owned by the transaction manager. F1 Setup additionally has its own unique_timer f1_setup_wait_timer for the time_to_wait retry case.
10. F1-C Transport (Brief)
F1AP is decoupled from the wire by the f1c_connection_client interface with three concrete implementations:
- SCTP server (CU side, listens for DU connections) — lib/f1ap/gateways/f1c_network_server_factory.cpp
- SCTP client (DU side, connects to CU) — lib/f1ap/gateways/f1c_network_client_factory.cpp
- Local connector (in-process when running the co-located
gnbbinary) — lib/f1ap/gateways/f1c_local_connector_factory.cpp
All inbound F1AP message handling runs on the ctrl_exec task executor passed to the impl constructor; per-UE DL SDU handling on the DU side additionally uses dedicated per-UE executors via f1ap_ue_executor_mapper. The factory choice is made by the application unit when wiring the gNB — the F1AP impl itself is identical across the three.
11. CU-CP ↔ F1AP-CU Integration (Brief)
The du_processor_impl in CU-CP owns one f1ap_cu_impl per connected DU. The contract back into CU-CP is f1ap_du_processor_notifier (include/ocudu/f1ap/cu_cp/f1ap_cu.h). Key callbacks:
on_ue_rrc_context_creation_request(...)— invoked on Initial UL RRC; creates RRC UE context and returns a UE-index handle.on_du_initiated_ue_context_release_request(...)— invoked on F1AP §8.3.6 (UE Context Release Request from DU).on_access_success(...)— invoked on F1AP §8.3.9 (CHO success); routes to mobility manager.on_transaction_info_loss(...)— invoked on DU disconnect / reset to scrub stale state.
F1AP exposes its own management interfaces back to CU-CP for symmetry: f1ap_message_handler, f1ap_ue_context_manager, f1ap_paging_manager, f1ap_nrppa_message_handler, f1ap_statistics_handler, f1ap_ue_context_removal_handler, f1ap_interface_management_handler.
12. DU-Manager ↔ F1AP-DU Integration (Brief)
The DU side is symmetric: du_manager_impl owns the f1ap_du_impl and implements the f1ap_du_configurator interface (include/ocudu/f1ap/du/f1ap_du.h). Key callbacks:
on_f1c_disconnection()— TNL loss; clean up state.request_reset(ues)— reset listed UE contexts (async).find_free_ue_index()— allocate a DU UE index when accepting a new UE.request_ue_creation(...)— instantiate MAC/RLC/PDCP entities for the new UE.request_ue_context_update(...)— apply DRB/SRB add/modify on UE Context Modification.request_ue_removal(...)— tear down on UE Context Release.request_ue_drb_deactivation(...)— flush SRB before release.
The UE-creation flow is: F1AP receives UEContextSetupRequest, allocates the DU UE index, calls request_ue_creation() async; du_manager creates the entity tree; F1AP registers per-bearer notifiers in the UE executor mapper; F1AP emits UEContextSetupResponse.
13. ASN.1 Layer (Brief)
Generated ASN.1 lives in lib/asn1/f1ap/ under namespace asn1::f1ap. Root PDU is asn1::f1ap::f1ap_pdu_c, a CHOICE of init_msg_s, successful_outcome_s, unsuccessful_outcome_s. Packing is done by lib/f1ap/f1ap_asn1_packer.{h,cpp} — pack(...) returns a byte_buffer for the gateway. ID conversions and IE-level helpers live in lib/f1ap/asn1_helpers.{h,cpp} and the side-specific f1ap_asn1_helpers.h files (SRB/DRB conversion, cause translation, int_to_gnb_du_ue_f1ap_id() and friends).
14. Procedure Cross-Reference
| TS 38.473 § | Procedure | Side(s) | File(s) | Pattern | Status |
|---|---|---|---|---|---|
| 8.2.1 | Reset (CU-init / DU-init) | DU RX / DU TX | du/procedures/f1ap_du_reset_procedure.h, du/procedures/f1ap_du_initiated_reset_procedure.h | Coroutine | Implemented |
| 8.2.2 | Error Indication | Both | f1ap_common_messages.h (generate_error_indication) | Helper | Implemented |
| 8.2.3 | F1 Setup | DU TX → CU RX | du/procedures/f1ap_du_setup_procedure.{h,cpp}, cu_cp/procedures/f1_setup_procedure.h | Coroutine, retry on time_to_wait | Implemented |
| 8.2.4 | gNB-DU Configuration Update | DU TX → CU RX | du/procedures/f1ap_du_gnbdu_config_update_procedure.h | Coroutine | Implemented |
| 8.2.5 | gNB-CU Configuration Update | CU TX → DU RX | cu_cp/procedures/gnb_cu_configuration_update_procedure.h, du/procedures/gnb_cu_configuration_update_procedure.h | Coroutine | Implemented |
| 8.2.6 | gNB-DU Resource Coordination | — | — | — | Not implemented |
| 8.2.8 | F1 Removal | CU TX → DU RX | cu_cp/procedures/f1_removal_procedure.h, du/procedures/f1ap_du_removal_procedure.h | Coroutine | Implemented |
| 8.3.2 | UE Context Setup | CU TX → DU RX | cu_cp/procedures/ue_context_setup_procedure.h, du/procedures/f1ap_du_ue_context_setup_procedure.h | Coroutine, per-UE txn | Implemented |
| 8.3.4 | UE Context Modification | CU TX → DU RX | cu_cp/procedures/ue_context_modification_procedure.h, du/procedures/f1ap_du_ue_context_modification_procedure.h | Coroutine, per-UE txn | Implemented |
| 8.3.5 | UE Context Release | CU TX → DU RX | cu_cp/procedures/ue_context_release_procedure.h, du/procedures/f1ap_du_ue_context_release_procedure.h | Coroutine, per-UE txn | Implemented |
| 8.3.6 | UE Context Release Request | DU TX → CU RX | du/f1ap_du_impl.cpp, cu_cp/f1ap_cu_impl.cpp | Direct dispatch | Implemented |
| 8.3.7 | UE Context Modification Required | DU TX → CU RX | du/f1ap_du_impl.cpp | Coroutine | Implemented |
| 8.3.8 | UE Inactivity Notification | DU TX | du/f1ap_du_impl.h (no-op) | — | Not implemented (stub) |
| 8.3.7 | Notify | DU TX | du/f1ap_du_impl.h (no-op) | — | Not implemented (stub) |
| 8.3.9 | Access Success | DU TX → CU RX | du/f1ap_du_impl.cpp, cu_cp/f1ap_cu_impl.cpp | Direct dispatch | Implemented |
| 8.4.1 | Initial UL RRC Message Transfer | DU TX → CU RX | cu_cp/f1ap_cu_impl.cpp (handle_initial_ul_rrc_message) | Direct dispatch | Implemented |
| 8.4.2 | DL RRC Message Transfer | CU TX → DU RX | cu_cp/f1ap_cu_impl.cpp, du/f1ap_du_impl.cpp | Direct dispatch | Implemented |
| 8.4.3 | UL RRC Message Transfer | DU TX → CU RX | du/f1ap_du_impl.cpp, cu_cp/f1ap_cu_impl.cpp | Direct dispatch | Implemented |
| 8.4.4 | RRC Delivery Report | DU TX | du/f1ap_du_impl.h (no-op) | — | Not implemented (stub) |
| 8.5 | Paging | CU TX → DU RX | cu_cp/f1ap_cu_impl.cpp, du/procedures/f1ap_du_paging_procedure.h | Direct dispatch | Implemented |
| 8.6 | System Information | — | — | — | Not implemented over F1AP |
| 8.7 | Warning Message Transmission | — | — | — | Not implemented |
| 8.8 | Trace | — | — | — | Not implemented |
| 8.13.3 | Positioning Measurement | CU TX → DU RX | cu_cp/procedures/f1ap_positioning_measurement_procedure.h, du/procedures/f1ap_du_positioning_measurement_procedure.h | Coroutine, per-UE txn | Implemented |
| 8.13.8 | TRP Information Exchange | CU TX → DU RX | cu_cp/procedures/f1ap_trp_information_exchange_procedure.h, du/procedures/f1ap_du_trp_information_exchange_procedure.h | Coroutine | Implemented |
| 8.13.9 | Positioning Information Exchange | CU TX → DU RX | cu_cp/procedures/f1ap_positioning_information_exchange_procedure.h, du/procedures/f1ap_du_positioning_information_exchange_procedure.h | Coroutine, per-UE txn | Implemented |
| 8.13.10 | Positioning Activation | CU TX → DU RX | cu_cp/procedures/f1ap_positioning_activation_procedure.h | Coroutine, per-UE txn | Implemented |
Entry points to read first: lib/f1ap/cu_cp/f1ap_cu_impl.h, lib/f1ap/du/f1ap_du_impl.h, then any single file under procedures/ on either side — they all share the shape described in §9. The two header files include/ocudu/f1ap/cu_cp/f1ap_cu.h and include/ocudu/f1ap/du/f1ap_du.h are the public contracts toward CU-CP and DU-Manager respectively.