FAPI#
5G Small Cell Forum (SCF) FAPI interface implementation for PHY-MAC communication with message capture and replay capabilities.
Overview#
The FAPI module provides a complete implementation of the 5G NR FAPI interface for communication between PHY and MAC layers. It includes state machine management, message routing over NVIPC transport, and file-based capture/replay for testing.
Key Features#
State Machine Management: Per-cell state tracking (Idle → Configured → Running → Stopped)
NVIPC Transport: High-performance shared memory message passing with RAII lifecycle management
Message Routing: Automatic dispatch of CONFIG, START, STOP requests with response generation
File Capture/Replay: Record and replay FAPI message sequences for deterministic testing
Callback System: User-configurable handlers for UL_TTI_REQUEST, DL_TTI_REQUEST, and other messages
Thread Safety: Lock-free slot management and thread-safe message operations
Core Concepts#
FAPI State Machine#
FapiState manages the complete FAPI message lifecycle over NVIPC transport. Each cell maintains its own state that transitions through the FAPI state machine based on received messages.
The NVIPC configuration can be provided either as a file path or inline YAML string. The state machine initializes transport endpoints and allocates per-cell state structures.
State Initialization#
// Configure FAPI state machine
ran::fapi::FapiState::InitParams params{};
params.nvipc_config_string =
ran::fapi::YamlConfigBuilder::create_primary_config("fapi_sample_init");
params.max_cells = 4;
params.max_sfn = 1024;
params.max_slot = 20;
// Initialize FAPI state
const ran::fapi::FapiState fapi_state(params);
Slot Management#
// Reset slot to (0, 0)
fapi_state.reset_slot();
// Get current slot
const auto slot = fapi_state.get_current_slot();
// Advance to next slot
fapi_state.increment_slot();
const auto next_slot = fapi_state.get_current_slot();
Slot management uses lock-free atomics for thread-safe operation. The slot counter automatically wraps around at configured SFN and slot limits.
Message Callbacks#
FapiState provides callbacks for handling different message types. Callbacks are invoked during message processing and can be used to forward messages to application logic.
Basic Message Callbacks#
std::size_t message_count{};
// Set callback to capture all messages
fapi_state.set_on_message(
[&message_count](const ran::fapi::FapiMessageData & /*msg*/) { message_count++; });
// Set callback for UL TTI requests
fapi_state.set_on_ul_tti_request([](std::uint16_t /*cell_id*/,
const scf_fapi_body_header_t & /*body_hdr*/,
std::uint32_t /*body_len*/) {
// Process UL TTI request
});
// Set callback for DL TTI requests
fapi_state.set_on_dl_tti_request([](std::uint16_t /*cell_id*/,
const scf_fapi_body_header_t & /*body_hdr*/,
std::uint32_t /*body_len*/) {
// Process DL TTI request
});
The on_message callback captures all messages before routing to
specific handlers, useful for logging or recording.
Configuration Callbacks#
// Set callback for CONFIG.request
fapi_state.set_on_config_request(
[](std::uint16_t /*cell_id*/,
const scf_fapi_body_header_t & /*body_hdr*/,
std::uint32_t /*body_len*/) -> scf_fapi_error_codes_t {
// Validate configuration
return static_cast<scf_fapi_error_codes_t>(SCF_FAPI_MSG_OK);
});
// Set callback for START.request
fapi_state.set_on_start_request(
[](std::uint16_t /*cell_id*/,
const scf_fapi_body_header_t & /*body_hdr*/,
std::uint32_t /*body_len*/) -> scf_fapi_error_codes_t {
// Initialize cell for operation
return static_cast<scf_fapi_error_codes_t>(SCF_FAPI_MSG_OK);
});
// Set callback for STOP.request
fapi_state.set_on_stop_request(
[](std::uint16_t /*cell_id*/,
const scf_fapi_body_header_t & /*body_hdr*/,
std::uint32_t /*body_len*/) -> scf_fapi_error_codes_t {
// Clean up cell resources
return static_cast<scf_fapi_error_codes_t>(SCF_FAPI_MSG_OK);
});
Configuration callbacks return error codes to indicate validation results. The state machine automatically sends appropriate responses or error indications based on callback return values.
File Capture and Replay#
FAPI messages can be captured to binary files during execution and replayed later for deterministic testing without NVIPC dependencies. This simplifies unit testing of downstream modules that depend on FAPI messages, such as PHY processing pipelines and ORAN C-plane message preparation.
Capturing Messages#
const auto output_path = get_test_output_dir() / "fapi_capture_sample.fapi";
// Create file writer
ran::fapi::FapiFileWriter writer(output_path.string());
// Create sample message data
ran::fapi::FapiMessageData msg{};
msg.cell_id = 0;
msg.msg_id = SCF_FAPI_DL_TTI_REQUEST;
std::vector<std::uint8_t> msg_buffer(128);
msg.msg_buf = std::span<const std::uint8_t>{msg_buffer.data(), msg_buffer.size()};
// Capture message
writer.capture_message(msg);
// Write to file
writer.flush_to_file();
FapiFileWriter buffers messages in memory during capture and writes them in a single operation to a binary file. The file format includes a header with message count and per-message metadata.
Reading Messages#
// Open FAPI capture file
ran::fapi::FapiFileReader reader(file_path.string());
// Read messages
std::size_t msg_count{};
while (auto msg = reader.read_next()) {
msg_count++;
}
FapiFileReader provides sequential or bulk access to captured messages:
ran::fapi::FapiFileReader reader(file_path.string());
// Read all messages at once
const auto all_messages = reader.read_all();
Replaying Messages#
FapiFileReplay provides timed replay of UL_TTI_REQUEST messages with automatic SFN/slot field updates:
static constexpr std::uint8_t SLOTS_PER_SUBFRAME = 2;
// Load FAPI capture file for replay
ran::fapi::FapiFileReplay replay(file_path.string(), SLOTS_PER_SUBFRAME);
// Get cell IDs
const auto &cell_ids = replay.get_cell_ids();
// Get request for current slot
for (const auto cell_id : cell_ids) {
auto req = replay.get_request_for_current_slot(cell_id);
if (req) {
// Process request (timing is updated automatically)
}
}
// Advance to next slot
const auto next_slot = replay.advance_slot();
The replay system maintains per-cell request indices and automatically updates timing fields in FAPI structures to match the current replay position. This enables deterministic testing with real capture data.
Additional Examples#
For complete working examples, see:
ran/runtime/fapi/tests/fapi_sample_tests.cpp- Documentation examples and basic usage patternsran/runtime/fapi/tests/fapi_state_tests.cpp- State machine tests with message processingran/runtime/fapi/tests/fapi_file_io_tests.cpp- File capture and reader testsran/runtime/fapi/tests/fapi_file_replay_tests.cpp- Replay system tests with timing validation
API Reference#
-
enum class ran::fapi::FapiStateT : std::uint8_t#
FAPI state machine states for each cell
Values:
-
enumerator FapiStateIdle#
Cell not configured.
-
enumerator FapiStateConfigured#
Cell configured but not running.
-
enumerator FapiStateRunning#
Cell running and processing slots.
-
enumerator FapiStateStopped#
Cell stopped after running.
-
enumerator FapiStateIdle#
-
template<typename T>
inline T *ran::fapi::assume_cast(void *ptr)# Cast a pointer assuming it’s safe
Use this for pointers where the caller has already ensured the pointer points to sufficient memory for type T (e.g., pointers returned from allocation or message construction functions). Centralizes reinterpret_cast with linter suppression.
Performs compile-time and runtime alignment checks:
Compile-time: Verifies type alignment is reasonable
Runtime: Validates pointer is properly aligned for type T
Note
For packed structs, alignof(T) == 1, so alignment checks verify byte-alignment only. The compiler handles unaligned field access, but this may cause performance penalties on some architectures.
Note
This cast is still technically UB per C++ standard (violates strict aliasing and object lifetime rules), but is widely used in systems/ networking code with proper precautions.
- Template Parameters:
T – Type to cast to
- Parameters:
ptr – [in] Pointer assumed to be safe
- Returns:
Pointer cast to type T
-
template<typename T>
inline const T *ran::fapi::assume_cast( - const void *ptr,
Cast a const pointer assuming it’s safe
Use this for pointers where the caller has already ensured the pointer points to sufficient memory for type T (e.g., pointers from validated messages). Centralizes reinterpret_cast with linter suppression.
Performs compile-time and runtime alignment checks:
Compile-time: Verifies type alignment is reasonable
Runtime: Validates pointer is properly aligned for type T
Note
For packed structs, alignof(T) == 1, so alignment checks verify byte-alignment only. The compiler handles unaligned field access, but this may cause performance penalties on some architectures.
Note
This cast is still technically UB per C++ standard (violates strict aliasing and object lifetime rules), but is widely used in systems/ networking code with proper precautions.
- Template Parameters:
T – Type to cast to
- Parameters:
ptr – [in] Pointer assumed to be safe
- Returns:
Const pointer cast to type T
-
template<typename T, typename U>
inline T &ran::fapi::assume_cast_ref( - U &ref,
Cast a reference assuming it’s safe
Use this for references where the caller has already ensured the reference is properly typed (e.g., message body headers). Centralizes reinterpret_cast with linter suppression.
Performs compile-time and runtime alignment checks:
Compile-time: Verifies type alignment is reasonable
Runtime: Validates reference address is properly aligned for type T
Note
For packed structs, alignof(T) == 1, so alignment checks verify byte-alignment only. The compiler handles unaligned field access, but this may cause performance penalties on some architectures.
Note
This cast is still technically UB per C++ standard (violates strict aliasing and object lifetime rules), but is widely used in systems/ networking code with proper precautions.
- Template Parameters:
T – Type to cast to
U – Source type of reference
- Parameters:
ref – [inout] Reference assumed to be safe
- Returns:
Reference cast to type T
-
template<typename T, typename U>
inline const T &ran::fapi::assume_cast_ref( - const U &ref,
Cast a const reference assuming it’s safe
Use this for references where the caller has already ensured the reference is properly typed (e.g., message body headers). Centralizes reinterpret_cast with linter suppression.
Performs compile-time and runtime alignment checks:
Compile-time: Verifies type alignment is reasonable
Runtime: Validates reference address is properly aligned for type T
Note
For packed structs, alignof(T) == 1, so alignment checks verify byte-alignment only. The compiler handles unaligned field access, but this may cause performance penalties on some architectures.
Note
This cast is still technically UB per C++ standard (violates strict aliasing and object lifetime rules), but is widely used in systems/ networking code with proper precautions.
- Template Parameters:
T – Type to cast to
U – Source type of reference
- Parameters:
ref – [in] Reference assumed to be safe
- Returns:
Const reference cast to type T
- inline std::span<std::byte> ran::fapi::make_buffer_span(
- void *ptr,
- const std::size_t length,
Create a byte span from a raw pointer and length
- Parameters:
ptr – [in] Raw pointer to data
length – [in] Length of the data in bytes
- Returns:
Byte span over the data
- inline std::span<const std::byte> ran::fapi::make_const_buffer_span(
- const void *ptr,
- const std::size_t length,
Create a const byte span from a raw pointer and length
- Parameters:
ptr – [in] Raw pointer to data
length – [in] Length of the data in bytes
- Returns:
Const byte span over the data
- ran::fapi::DECLARE_LOG_COMPONENT(
- FapiComponent,
- FapiCore,
- FapiState,
- FapiMsg,
- FapiSample,
- FapiFileReplay,
Declare logging components for FAPI subsystem
- std::string ran::fapi::create_default_nvipc_config(
- std::string_view prefix,
Create default NVIPC configuration YAML string
Generates standard NVIPC configuration for PHY-MAC interface with customizable prefix. The configuration includes default buffer sizes, memory pool settings, and application configuration suitable for most FAPI applications.
- Parameters:
prefix – [in] NVIPC shared memory prefix (e.g., “fapi_sample”, “phy_ran_app”)
- Returns:
YAML configuration string ready for FapiState initialization
- tl::expected<std::filesystem::path, std::string> ran::fapi::get_fapi_capture_file_path(
Get FAPI capture file path from environment variables
Reads FAPI_CAPTURE_DIR and TEST_CELLS environment variables, validates their values, and constructs the path to the FAPI capture file.
- Returns:
Path to FAPI capture file on success, error message on failure
-
struct CapturedFapiMessage#
- #include <fapi_file_writer.hpp>
Captured FAPI message
Used by both FapiFileWriter and FapiFileReader for storing FAPI message data with optional data buffer.
-
struct CellConfig#
- #include <fapi_state.hpp>
Per-cell configuration and state
Public Members
-
std::atomic<FapiStateT> state = {FapiStateT::FapiStateIdle}#
Current FAPI state (atomic for thread-safe access)
-
uint16_t cell_id = {}#
Cell index.
-
uint16_t phy_cell_id = {}#
Physical cell ID from CONFIG.request.
-
uint16_t num_rx_ant = {0}#
Number of RX antennas from CONFIG.request.
-
std::atomic<FapiStateT> state = {FapiStateT::FapiStateIdle}#
-
struct FapiFileHeader#
- #include <fapi_file_writer.hpp>
File format header (16 bytes)
-
class FapiFileReader#
- #include <fapi_file_reader.hpp>
FAPI message file reader
Reads FAPI messages from binary files created by FapiFileWriter. Provides sequential access to captured messages for replay or analysis.
Usage:
FapiFileReader reader("/tmp/capture.fapi"); std::map<std::uint16_t, std::vector<std::vector<std::uint8_t>>> fapi_messages; while (auto msg = reader.read_next()) { if (msg->msg_data.empty()) { continue; } const std::uint16_t cell_id = msg->cell_id; fapi_messages[cell_id].emplace_back(msg->msg_data.begin(), msg->msg_data.end()); }
Thread safety: Not thread-safe. External synchronization required.
Public Functions
-
explicit FapiFileReader(std::string input_path)#
Open and validate FAPI file
- Parameters:
input_path – [in] Path to input file
- Throws:
std::runtime_error – if file cannot be opened or is invalid
-
std::optional<CapturedFapiMessage> read_next()#
Read next message from file
- Throws:
std::runtime_error – if file is corrupted
- Returns:
Message if available, std::nullopt if EOF or error
-
std::vector<CapturedFapiMessage> read_all()#
Read all remaining messages from file
Reads all messages from current position to end of file. Useful for loading entire capture files into memory.
- Throws:
std::runtime_error – if file is corrupted
- Returns:
Vector of all remaining messages
-
void reset()#
Reset reader to beginning of file
Seeks back to first message for re-reading.
-
std::size_t get_total_message_count() const noexcept#
Get total message count from file header
- Returns:
Total number of messages in file
-
std::size_t get_messages_read() const noexcept#
Get number of messages read so far
- Returns:
Count of messages read
-
bool is_eof() const noexcept#
Check if at end of file
- Returns:
true if EOF or all messages read
-
explicit FapiFileReader(std::string input_path)#
-
class FapiFileReplay#
- #include <fapi_file_replay.hpp>
FAPI file replay state
Manages replaying captured FAPI UL_TTI_REQUEST messages with proper timing updates. Tracks current slot position and updates SFN/slot fields in FAPI buffers to match current replay position.
Public Functions
- explicit FapiFileReplay(
- const std::string &fapi_file_path,
- std::uint8_t slots_per_subframe,
Load FAPI UL_TTI_REQUEST messages from capture file
- Parameters:
fapi_file_path – [in] Path to .fapi capture file
slots_per_subframe – [in] Slots per subframe (numerology-dependent)
- Throws:
std::runtime_error – if file cannot be loaded or contains no valid messages
-
std::uint64_t advance_slot()#
Advance to next slot
Increments the absolute slot counter and updates frame/subframe/slot_id state. For each cell, checks if the current request matched the previous slot (before advancing). If a match is found, that request was consumed, so advances that cell’s request index to the next request (with wraparound).
This centralizes the file state update in one place. After calling this method, get_request_for_current_slot() will return requests for the new slot.
This should be called once per slot by the application, not per cell.
- Returns:
Current absolute slot number after increment
- std::optional<RequestWithSize> get_request_for_current_slot(
- std::uint16_t cell_id,
Get request for current slot and cell
Returns the FAPI request buffer for the given cell that matches the current slot timing. Updates the SFN and slot fields in the buffer to match current replay position. Returns std::nullopt if no matching request or cell not found.
This method can be called multiple times for the same slot without side effects on the request index state (which is advanced by advance_slot()).
Note
This method updates the returned FAPI buffer’s timing fields (sfn, slot) to match the current replay position, but does not advance internal request indices.
- Parameters:
cell_id – [in] Cell identifier
- Returns:
Optional RequestWithSize containing pointer and body_len, or std::nullopt if no match
-
const std::vector<std::uint16_t> &get_cell_ids() const noexcept#
Get all cell IDs present in loaded data
- Returns:
Const reference to vector of cell IDs
-
std::size_t get_request_count(std::uint16_t cell_id) const noexcept#
Get number of requests for a cell
- Parameters:
cell_id – [in] Cell identifier
- Returns:
Number of requests, or 0 if cell not found
-
std::size_t get_total_request_count() const noexcept#
Get total request count across all cells
- Returns:
Total number of requests
-
inline std::size_t get_cell_count() const noexcept#
Get number of cells
- Returns:
Cell count
-
inline std::uint64_t get_current_absolute_slot() const noexcept#
Get current absolute slot number
- Returns:
Current absolute slot
-
FapiSlotTiming get_current_slot_timing() const noexcept#
Get current slot timing
- Returns:
Current frame/subframe/slot timing
-
struct RequestWithSize#
- #include <fapi_file_replay.hpp>
Result of request lookup containing pointer and body length
Public Members
-
scf_fapi_ul_tti_req_t *request = {}#
Non-owning pointer to request structure (owned by FapiFileReplay)
-
std::size_t body_len = {}#
Body length (buffer size minus body header)
-
scf_fapi_ul_tti_req_t *request = {}#
-
class FapiFileWriter#
- #include <fapi_file_writer.hpp>
FAPI message file writer
Captures FAPI messages to memory during execution and writes them to a binary file on flush. Designed for use with FapiState callbacks to record messages for later replay without NVIPC dependencies.
Usage:
FapiFileWriter writer("/tmp/capture.fapi"); fapi_state.set_on_message([&writer](const FapiMessageData& msg) { writer.capture_message(msg); }); // ... run test ... writer.flush_to_file();
Thread safety: Not thread-safe. External synchronization required if called from multiple threads.
Public Functions
- explicit FapiFileWriter(
- std::string output_path,
- std::size_t initial_capacity = DEFAULT_INITIAL_CAPACITY,
Construct file writer
- Parameters:
output_path – [in] Path to output file (will be created/overwritten)
initial_capacity – [in] Initial message capacity to reserve
-
void capture_message(const FapiMessageData &msg)#
Capture a message to memory buffer
Called from FapiState on_message callback. Copies message data to internal buffer for later writing.
- Parameters:
msg – [in] Message data to capture
-
void flush_to_file()#
Write all buffered messages to file
Writes file header followed by all captured message records. Should be called once at end of capture session.
- Throws:
std::runtime_error – if file operations fail
-
std::size_t get_message_count() const noexcept#
Get number of captured messages
- Returns:
Count of messages in buffer
-
std::size_t get_buffer_size_bytes() const noexcept#
Get total buffer size in bytes
- Returns:
Total size of all captured data including headers
Public Static Attributes
-
static constexpr std::size_t DEFAULT_INITIAL_CAPACITY = 1000#
Default message capacity.
-
struct FapiMessageData#
- #include <fapi_state.hpp>
Message data for capture/replay
Contains raw FAPI message data without transport-specific dependencies. Uses std::span for zero-copy view of message buffers.
-
struct FapiMessageRecordHeader#
- #include <fapi_file_writer.hpp>
Message record header (12 bytes)
-
struct FapiSlotTiming#
- #include <fapi_file_replay.hpp>
Slot timing information for FAPI replay
Contains raw timing data needed for conversion to ORAN slot timing. This is independent of ORAN to avoid circular dependencies.
-
class FapiState#
- #include <fapi_state.hpp>
FAPI state machine manager for 5G NR PHY-MAC interface
Provides comprehensive management of FAPI message processing, including:
NVIPC transport lifecycle (initialization, message send/receive, cleanup via RAII)
Per-cell state machines (Idle → Configured → Running → Stopped transitions)
Message routing and validation for CONFIG/START/STOP.request messages
User-configurable callbacks for UL_TTI_REQUEST, DL_TTI_REQUEST, SLOT_RESPONSE forwarding
Automatic SLOT.indication generation with SFN/slot tracking and wraparound
ERROR.indication and STOP.indication transmission
Message flow:
Receive messages via NVIPC (receive_message)
Process and route via process_message (handles state transitions, invokes callbacks)
Send indications via NVIPC (send_slot_indication, send_stop_indication, etc.)
State machine: Each cell independently transitions through states based on CONFIG.request → START.request → STOP.request message sequence.
Thread safety:
Thread-safe methods (can be called concurrently from multiple threads):
get_cell_state(), get_num_cells_configured(), get_num_cells_running()
allocate_message(), receive_message(), send_message(), release_message()
process_message() (cell state transitions use atomics; nvipc provides buffer synchronization)
increment_slot(), reset_slot(), get_current_slot() (use packed atomic for slot/sfn)
send_slot_indication(), send_config_response(), send_stop_indication(), send_error_indication()
NOT thread-safe methods (require external synchronization if used from multiple threads):
All callback setters (set_on_*)
Note: nvipc operations (allocate/send/receive/release) are internally thread-safe; memory fences ensure proper buffer visibility between TX and RX threads. Slot management uses lock-free atomics with packed uint32_t representation (sfn in upper 16 bits, slot in lower 16 bits).
Note
Destructor automatically frees NVIPC resources and unlinks /dev/shm files via RAII through NvIpcDeleter.
Public Types
-
using OnUlTtiRequestCallback = std::function<void(uint16_t cell_id, const scf_fapi_body_header_t &body_hdr, uint32_t body_len)>#
Callback function type for UL TTI request events
- Param cell_id:
[in] Cell identifier
- Param body_hdr:
[in] Message body header
- Param body_len:
[in] Length of message body
-
using OnDlTtiRequestCallback = std::function<void(uint16_t cell_id, const scf_fapi_body_header_t &body_hdr, uint32_t body_len)>#
Callback function type for DL TTI request events
- Param cell_id:
[in] Cell identifier
- Param body_hdr:
[in] Message body header
- Param body_len:
[in] Length of message body
-
using OnSlotResponseCallback = std::function<void(uint16_t cell_id, const scf_fapi_body_header_t &body_hdr, uint32_t body_len)>#
Callback function type for slot response events
- Param cell_id:
[in] Cell identifier
- Param body_hdr:
[in] Message body header
- Param body_len:
[in] Length of message body
-
using OnConfigRequestCallback = std::function<scf_fapi_error_codes_t(uint16_t cell_id, const scf_fapi_body_header_t &body_hdr, uint32_t body_len)>#
Callback function type for config request events
Called when a CONFIG.request is received. Return error code to indicate success or failure.
- Param cell_id:
[in] Cell identifier
- Param body_hdr:
[in] Message body header
- Param body_len:
[in] Length of message body
- Return:
Error code indicating validation result
-
using OnStartRequestCallback = std::function<scf_fapi_error_codes_t(uint16_t cell_id, const scf_fapi_body_header_t &body_hdr, uint32_t body_len)>#
Callback function type for start request events
Called when a START.request is received. Return error code to indicate success or failure.
- Param cell_id:
[in] Cell identifier
- Param body_hdr:
[in] Message body header
- Param body_len:
[in] Length of message body
- Return:
Error code indicating validation result
-
using OnStopRequestCallback = std::function<scf_fapi_error_codes_t(uint16_t cell_id, const scf_fapi_body_header_t &body_hdr, uint32_t body_len)>#
Callback function type for stop request events
Called when a STOP.request is received. Return error code to indicate success or failure.
- Param cell_id:
[in] Cell identifier
- Param body_hdr:
[in] Message body header
- Param body_len:
[in] Length of message body
- Return:
Error code indicating validation result
-
using OnMessageCallback = std::function<void(const FapiMessageData &msg)>#
Callback function type for capturing all messages
Called for every message before routing to specific handlers. Provides raw message data for recording/replay purposes without NVIPC dependencies.
- Param msg:
[in] Message data including buffers and metadata
Public Functions
-
explicit FapiState(const InitParams ¶ms)#
Construct and initialize FAPI state machine
Initializes NVIPC from config file or string in constructor. If nvipc_config_file is provided, uses file; otherwise uses nvipc_config_string. Throws std::runtime_error if NVIPC initialization fails.
- Parameters:
params – [in] Configuration parameters
-
int allocate_message(nv_ipc_msg_t &msg)#
Allocate a TX message buffer with proper synchronization
Allocates a buffer from the NVIPC free pool with acquire fence to ensure the buffer is clean after allocation.
- Parameters:
msg – [out] Message structure to populate
- Returns:
0 on success, negative on failure
-
int receive_message(nv_ipc_msg_t &msg)#
Receive a message from NVIPC
Non-blocking receive. Returns negative value if no message available. Forwards the return code from NVIPC rx_recv_msg().
- Parameters:
msg – [out] Message structure to populate
- Returns:
>= 0 on success, < 0 if no message available (NVIPC returns -1)
-
void release_message(nv_ipc_msg_t &msg)#
Release a message buffer back to NVIPC
Must be called after processing each received message.
- Parameters:
msg – [inout] Message to release
-
scf_fapi_error_codes_t process_message(nv_ipc_msg_t &msg)#
Process incoming FAPI message (main entry point)
Routes message to appropriate handler based on message type. Handles CONFIG.request, START.request, STOP.request, and callbacks for UL_TTI_REQUEST, DL_TTI_REQUEST, SLOT_RESPONSE.
- Parameters:
msg – [inout] NVIPC message to process
- Returns:
Error code indicating success (MSG_OK) or failure reason
-
bool send_slot_indication()#
Send SLOT.indication to all running cells (thread-safe)
Atomically captures current slot at start to ensure consistency across all cells in a single invocation.
- Returns:
true if all messages sent successfully
-
bool send_stop_indication(uint16_t cell_id)#
Send STOP.indication message for a cell
- Parameters:
cell_id – [in] Cell identifier
- Returns:
true if message sent successfully
- bool send_error_indication(
- uint16_t cell_id,
- scf_fapi_message_id_e msg_id,
- scf_fapi_error_codes_t error_code,
Send ERROR.indication message (thread-safe)
Atomically captures current slot to include in error indication.
- Parameters:
cell_id – [in] Cell identifier
msg_id – [in] Message ID that caused error
error_code – [in] Error code to report
- Returns:
true if message sent successfully
-
void increment_slot()#
Increment slot counter with wraparound (thread-safe)
Advances to next slot, wrapping SFN and slot as needed. Uses lock-free compare-and-swap to handle concurrent access.
-
void reset_slot()#
Reset slot counter to (0, 0) (thread-safe)
Atomically resets both SFN and slot to zero.
-
SlotInfo get_current_slot() const noexcept#
Get current slot information (thread-safe)
Atomically reads current SFN and slot without tearing.
- Returns:
Current SFN and slot
-
FapiStateT get_cell_state(uint16_t cell_id) const noexcept#
Get state of a specific cell
- Parameters:
cell_id – [in] Cell identifier
- Returns:
Cell state, or idle if invalid cell_id
-
std::size_t get_num_cells_configured() const noexcept#
Get number of configured cells
- Returns:
Count of cells in configured or later states
-
std::size_t get_num_cells_running() const noexcept#
Get number of running cells
- Returns:
Count of cells in running state
-
void set_on_ul_tti_request(OnUlTtiRequestCallback callback)#
Set callback for UL TTI request events
- Parameters:
callback – [in] Callback function to invoke on UL TTI request
-
void set_on_dl_tti_request(OnDlTtiRequestCallback callback)#
Set callback for DL TTI request events
- Parameters:
callback – [in] Callback function to invoke on DL TTI request
-
void set_on_slot_response(OnSlotResponseCallback callback)#
Set callback for slot response events
- Parameters:
callback – [in] Callback function to invoke on slot response
-
void set_on_config_request(OnConfigRequestCallback callback)#
Set callback for config request events
- Parameters:
callback – [in] Callback function to invoke on CONFIG.request
-
void set_on_start_request(OnStartRequestCallback callback)#
Set callback for start request events
- Parameters:
callback – [in] Callback function to invoke on START.request
-
void set_on_stop_request(OnStopRequestCallback callback)#
Set callback for stop request events
- Parameters:
callback – [in] Callback function to invoke on STOP.request
-
void set_on_message(OnMessageCallback callback)#
Set callback for capturing all messages
This callback is invoked before message-specific callbacks, allowing capture of all messages for recording/replay purposes.
- Parameters:
callback – [in] Callback function to invoke for every message
-
struct InitParams#
- #include <fapi_state.hpp>
Configuration parameters for FapiState
Public Members
-
std::string nvipc_config_file#
Full path to NVIPC config YAML.
-
std::string nvipc_config_string#
NVIPC config YAML as string (used if nvipc_config_file is empty)
-
std::size_t max_cells = {DEFAULT_MAX_CELLS}#
Maximum supported cells.
-
uint16_t max_sfn = {DEFAULT_MAX_SFN}#
Maximum SFN value (wraps to 0)
-
uint16_t max_slot = {DEFAULT_MAX_SLOT}#
Maximum slot value (wraps to 0)
-
std::string nvipc_config_file#
-
struct SlotInfo#
- #include <fapi_state.hpp>
5G NR slot timing information
Public Functions
-
class YamlConfigBuilder#
- #include <fapi_test_utils.hpp>
Helper class for building NVIPC YAML configurations for tests
Public Static Functions
- static std::string create_primary_config(
- const std::string &prefix = "fapi_test",
Create primary NVIPC configuration
- Parameters:
prefix – [in] NVIPC prefix for shared memory
- Returns:
YAML configuration string
- static std::string create_secondary_config(
- const std::string &prefix = "fapi_test",
Create secondary NVIPC configuration
- Parameters:
prefix – [in] NVIPC prefix for shared memory
- Returns:
YAML configuration string