Fronthaul#

ORAN fronthaul interface for C-Plane and U-Plane packet processing.

Overview#

The Fronthaul library provides ORAN (Open Radio Access Network) fronthaul processing for 5G Radio Units (RUs). It handles both Control-Plane (C-Plane) and User-Plane (U-Plane) packet flows with precise timing and low latency.

Key Features#

  • C-Plane Processing: Convert FAPI messages to ORAN C-Plane packets and transmit via DPDK

  • U-Plane Processing: Receive and reorder U-Plane packets using GPU- accelerated Order Kernel pipeline

  • YAML Configuration: Parse RU emulator configuration files

  • Timing Management: Calculate packet send times with nanosecond precision

  • Statistics Tracking: Monitor packets sent, errors, and throughput

Core Concepts#

C-Plane Configuration#

Configure the Fronthaul library with network settings, cell parameters, timing windows (T1a min/max), and antenna port configuration for ORAN C-Plane operation.

// Build fronthaul configuration
FronthaulConfig config{};

// Network configuration - NIC address
config.net_config.nic_config.nic_pcie_addr = "0000:17:00.0";

// Cell configuration - destination MACs and VLANs
config.cell_dest_macs.push_back({{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}});
config.cell_vlan_tcis.push_back(0xE002); // VLAN 2, PCP 7

// ORAN parameters
config.numerology = ran::oran::from_scs(ran::oran::SubcarrierSpacing::Scs30Khz);
config.num_antenna_ports = 4;
config.mtu = 1514;

// Timing parameters
config.slot_ahead = 1;
config.t1a_max_cp_ul_ns = 285'000; // 285us
config.t1a_min_cp_ul_ns = 234'000; // 234us

// Access configuration
const auto num_cells = config.cell_dest_macs.size();
const auto num_ports = config.num_antenna_ports;
const auto mtu_size = config.mtu;

U-Plane Configuration#

U-Plane configuration controls the Order Kernel pipeline for receiving and processing U-Plane packets. The configuration includes timing windows (Ta4 early/late), packet buffer sizes, and timeout parameters.

// Create U-Plane configuration with default settings
UPlaneConfig uplane_config{};

// Customize timing windows for 30kHz SCS
uplane_config.ta4_min_ns = 50'000;        // 50us early window
uplane_config.ta4_max_ns = 450'000;       // 450us late window
uplane_config.slot_duration_ns = 500'000; // 500us slot

// Configure packet reception
uplane_config.num_packets = 16384;    // 16K packet buffers
uplane_config.max_packet_size = 8192; // 8KB max packet size

// Access configured values
const auto ta4_min = uplane_config.ta4_min_ns;
const auto ta4_max = uplane_config.ta4_max_ns;
const auto num_pkts = uplane_config.num_packets;

Packet Timing#

Accurate packet timing is critical for ORAN fronthaul. The library calculates packet send times based on slot timing, T1a windows (C-Plane timing advance window relative to data slot boundary), and TAI offset (International Atomic Time for GPS synchronization).

// Calculate packet send time for a slot
const PacketSendTimeParams params{
        .t0 = 0ns,
        .tai_offset = 0ns,
        .absolute_slot = 100,
        .slot_period = 500us,
        .slot_ahead = 1,
        .t1a_max_cp_ul = 285us,
        .actual_start = 50ms};

const auto result = calculate_packet_send_time(params);

// Access timing results
const auto actual_start = result.actual_start;
const auto start_tx = result.start_tx;

Packet Headers#

ORAN C-Plane packets require proper Ethernet, VLAN, and eCPRI headers. The library provides a helper to create packet header templates.

// Create packet header template for ORAN C-Plane
const framework::net::MacAddress src_mac{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
const framework::net::MacAddress dest_mac{{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}};
const std::uint16_t vlan_tci = 0xE002; // VLAN 2, PCP 7
const std::uint16_t eac_id = 0;        // Enhanced antenna carrier ID

const auto header = create_packet_header_template(src_mac, dest_mac, vlan_tci, eac_id);

// Header contains ethernet, VLAN, and eCPRI fields
const auto header_size = sizeof(header);

Statistics#

The Fronthaul class tracks operational statistics including packets sent, requests sent, errors, and average packets per request.

// Create statistics structure
FronthaulStats stats{};
stats.requests_sent = 1000;
stats.packets_sent = 4000;
stats.send_errors = 0;
stats.avg_packets_per_request = 4.0;

// Access statistics
const auto total_requests = stats.requests_sent;
const auto total_packets = stats.packets_sent;
const auto avg_packets = stats.avg_packets_per_request;
const auto errors = stats.send_errors;

Usage Example#

The Fronthaul library requires hardware resources (DPDK, NIC, GPU) for actual operation. The following examples are extracted from the complete sample application.

Fronthaul Configuration#

// 6. Create and return fronthaul config with complete net_config
static constexpr std::uint32_t SCS_KHZ = 30;
return ran::fronthaul::FronthaulConfig{
        .net_config = net_config,
        .cell_dest_macs = cell_macs,
        .cell_vlan_tcis = cell_vlans,
        .numerology = ran::oran::from_scs_khz(SCS_KHZ),
        .slot_ahead = slot_ahead,
        .t1a_max_cp_ul_ns = yaml_config->timing.t1a_max_ns,
        .t1a_min_cp_ul_ns = yaml_config->timing.t1a_min_ns,
        .uplane_config = uplane_config,
};

Fronthaul Construction#

// U-Plane configuration is already set in fh_config from create_fronthaul_config_from_yaml
RT_LOGC_INFO(
        rf::FronthaulApp::UPlane,
        "U-Plane configured: slot_duration={}ns, Ta4 window=[{}ns, {}ns], RU MAC={}",
        fh_config.uplane_config.slot_duration_ns,
        fh_config.uplane_config.ta4_min_ns,
        fh_config.uplane_config.ta4_max_ns,
        fh_config.cell_dest_macs[0].to_string());

// Create fronthaul instance (now handles both C-Plane and U-Plane)
rf::Fronthaul fronthaul(fh_config);

Sending C-Plane Messages#

// Send C-plane for this cell
// Request already has updated sfn/slot from FapiFileReplay
const auto &req_info = request_opt.value();
fronthaul.send_ul_cplane(
        *req_info.request, req_info.body_len, cell_id, absolute_slot, t0, tai_offset);

Processing U-Plane#

// Get current slot timing and convert to ORAN format
const auto oran_slot_timing =
        ran::oran::fapi_to_oran_slot_timing(fapi_replay.get_current_slot_timing());

try {
    fronthaul.process_uplane(oran_slot_timing);
} catch (const std::exception &e) {
    RT_LOGC_ERROR(rf::FronthaulApp::UPlane, "Failed to process U-Plane: {}", e.what());
}

Accessing Statistics#

RT_LOGC_INFO(rf::FronthaulApp::Stats, "\n=== Fronthaul Statistics ===");
RT_LOGC_INFO(rf::FronthaulApp::Stats, "{}", fronthaul.get_stats());

For the complete working example with task scheduling, timing synchronization, and FAPI replay, see ran/runtime/fronthaul/samples/fronthaul_app.cpp.

Additional Examples#

For more examples with executable code, see:

  • ran/runtime/fronthaul/tests/fronthaul_sample_tests.cpp - Configuration and utility examples

  • ran/runtime/fronthaul/samples/fronthaul_app.cpp - Complete application with Fronthaul construction

  • ran/runtime/fronthaul/samples/fronthaul_app_utils.cpp - C-Plane/U-Plane processing and statistics

API Reference#

constexpr std::size_t ran::fronthaul::ORDER_KERNEL_MAX_CELLS_PER_SLOT = 1#

Maximum number of cells that can be processed per slot.

constexpr std::uint32_t ran::fronthaul::DEFAULT_DPDK_CORE_ID = 0#

DPDK core for network operations (default: core 0 for receiver)

constexpr std::uint16_t ran::fronthaul::ORAN_ORU_ETHER_TYPE = 0xaefe#

O-RAN eCPRI EtherType used by production O-RUs.

constexpr std::uint64_t ran::fronthaul::DEFAULT_TIMEOUT_NO_PKT_NS = to_nanoseconds(std::chrono::milliseconds(6))#

Default timeout when no packets received (6 milliseconds)

constexpr std::uint64_t ran::fronthaul::DEFAULT_TIMEOUT_FIRST_PKT_NS = to_nanoseconds(std::chrono::microseconds(1'500))#

Default timeout for first packet reception (1500 microseconds)

constexpr std::uint64_t ran::fronthaul::DEFAULT_TIMEOUT_LOG_INTERVAL_NS = to_nanoseconds(std::chrono::seconds(1))#

Default log interval for timeout messages (1 second)

constexpr std::uint8_t ran::fronthaul::DEFAULT_TIMEOUT_LOG_ENABLE = 1#

Default timeout log enable flag (1=enabled, 0=disabled)

constexpr std::uint32_t ran::fronthaul::DEFAULT_MAX_RX_PKTS = 512#

Default maximum packets to receive per kernel call.

constexpr std::uint64_t ran::fronthaul::DEFAULT_RX_PKTS_TIMEOUT_NS = to_nanoseconds(std::chrono::microseconds(100))#

Default RX packet timeout between packets (100 microseconds)

constexpr std::uint32_t ran::fronthaul::MAX_ANTENNA_PORTS_PER_SLOT = 4#

Maximum number of antenna ports (eAxC IDs) per slot.

constexpr int ran::fronthaul::PUSCH_NUM_PRB = 273#

PUSCH resource configuration for 100MHz bandwidth.

Number of PRBs

constexpr int ran::fronthaul::NUM_ANTENNA_PORTS = 4#

Number of antenna ports.

constexpr int ran::fronthaul::PUSCH_RE_PER_PRB = 12#

Resource elements per PRB.

constexpr std::uint32_t ran::fronthaul::ORAN_PUSCH_SYMBOLS_X_SLOT = 14#

PUSCH symbols per slot.

constexpr std::size_t ran::fronthaul::PUSCH_REAL_IMAG = 2#

PUSCH tensor dimensions for TensorInfo (FP16 complex, real/imag interleaved)

Real + imaginary components

constexpr std::size_t ran::fronthaul::PUSCH_NUM_ELEMENTS = static_cast<std::size_t>(PUSCH_NUM_PRB) * PUSCH_RE_PER_PRB * ORAN_PUSCH_SYMBOLS_X_SLOT * NUM_ANTENNA_PORTS * PUSCH_REAL_IMAG#

Total number of FP16 elements in PUSCH buffer (273 × 12 × 14 × 4 × 2 = 366,912)

constexpr std::size_t ran::fronthaul::PUSCH_SIZE_BYTES = PUSCH_NUM_ELEMENTS * sizeof(__half)#

Total size of PUSCH buffer in bytes (366,912 × 2 = 733,824 bytes)

PacketSendTimeResult ran::fronthaul::calculate_packet_send_time(
const PacketSendTimeParams &params,
)#

Calculate packet send time for a slot

This function computes when C-plane packets should be transmitted to the NIC, accounting for processing advance time, T1a timing windows, and TAI offset.

This is exposed for unit testing purposes.

Parameters:

params[in] Input parameters for packet send time calculation

Returns:

Packet send time calculation results

ran::oran::PacketHeaderTemplate ran::fronthaul::create_packet_header_template(
const framework::net::MacAddress &src_mac,
const framework::net::MacAddress &dest_mac,
std::uint16_t vlan_tci,
std::uint16_t enhanced_antenna_carrier,
)#

Create packet header template for ORAN C-Plane messages

Parameters:
  • src_mac[in] Source MAC address (from NIC)

  • dest_mac[in] Destination MAC address

  • vlan_tci[in] VLAN tag control information

  • enhanced_antenna_carrier[in] Enhanced antenna carrier ID (encodes cell and antenna port)

Returns:

Packet header template ready for ORAN flow

ran::fronthaul::DECLARE_LOG_COMPONENT(
FronthaulLog,
FronthaulGeneral,
FronthaulParser,
FronthaulTiming,
FronthaulNetwork,
FapiFileReplay,
)#

Declare logging components for fronthaul subsystem

ran::fronthaul::DECLARE_LOG_COMPONENT(
FronthaulKernels,
OrderModule,
OrderPipeline,
OrderFactory,
OrderMemory,
OrderKernel,
OrderDoca,
)#

Fronthaul Kernels Logging Components

Defines component categories for fronthaul U-plane (order kernel). Organized by functional area for filtering and organization.

Order Kernel (U-plane) Components:

  • OrderModule: OrderKernelModule lifecycle, port configuration, execution

  • OrderPipeline: OrderKernelPipeline setup, routing, graph management

  • OrderFactory: Module and pipeline factory operations

  • OrderMemory: Memory allocation, GDRCopy buffer management, descriptors

  • OrderKernel: CUDA kernel launch, parameters, device function calls

  • OrderDoca: DOCA RX queue interaction, semaphore handling, packet processing

ran::fronthaul::DECLARE_LOG_COMPONENT(
FronthaulApp,
App,
UPlane,
CPlane,
Config,
Stats,
)#

Fronthaul Application Logging Components

Defines component categories for fronthaul sample application. Used for application-level logging in samples/ directory.

Components:

  • App: CLI parsing, initialization, application lifecycle

  • UPlane: U-Plane message processing

  • CPlane: C-Plane message processing

  • Config: YAML configuration parsing

  • Stats: Statistics display and reporting

tl::expected<FronthaulYamlConfig, std::string> ran::fronthaul::parse_fronthaul_config(
const std::filesystem::path &config_file_path,
)#

Parse fronthaul configuration from RU emulator YAML file

Extracts:

  • Cell configurations (MAC addresses, VLANs)

  • O-RAN timing parameters (t1a_max, t1a_min in µs, converted to ns)

  • MTU size

Parameters:

config_file_path[in] Path to ru_emulator_config.yaml

Returns:

Parsed configuration on success, error message on failure

tl::expected<FronthaulYamlConfig, std::string> ran::fronthaul::parse_fronthaul_config_from_string(
std::string_view yaml_content,
)#

Parse fronthaul configuration from YAML string

Parameters:

yaml_content[in] YAML content as string

Returns:

Parsed configuration on success, error message on failure

template<bool, uint8_t, uint8_t, int, int>
void ran::fronthaul::order_kernel_doca_single_subSlot_pingpong(
const OrderKernelStaticDescriptor *static_desc,
const OrderKernelDynamicDescriptor *dynamic_desc,
)#

Unified ORAN order kernel with descriptor-based interface

Template parameters used by OrderKernelModule:

  • ok_tb_enable = false (no test bench)

  • ul_rx_pkt_tracing_level = 0 (no packet tracing)

  • srs_enable = 0 (PUSCH only)

  • NUM_THREADS = 320

  • NUM_CTAS_PER_SM = 1

Parameters:
  • static_desc[in] Static kernel parameters (GDRCopy buffers, DOCA handles)

  • dynamic_desc[in] Dynamic kernel parameters (timing, frame/slot IDs)

template<typename Rep, typename Period>
constexpr std::uint64_t ran::fronthaul::to_nanoseconds(
std::chrono::duration<Rep, Period> duration,
)#

Convert duration to nanoseconds at compile-time

Template Parameters:
  • Rep – Arithmetic type representing the number of ticks

  • Period – std::ratio representing the tick period

Parameters:

duration[in] Duration to convert

Returns:

Duration value in nanoseconds

void ran::fronthaul::populate_uplane_env_config(
framework::net::EnvConfig &config,
const FronthaulYamlConfig &yaml_config,
const UPlaneConfig &uplane_config,
)#

Populate network environment configuration with U-Plane DOCA RX queue settings

Adds DOCA GPUNetIO RX queue configuration to an existing EnvConfig for receiving O-RAN U-Plane packets with GPU-accelerated packet processing via the Order Kernel pipeline.

The input EnvConfig must already contain:

  • nic_pcie_addr (from C-plane configuration)

  • gpu_device_id (from C-plane configuration)

  • DPDK configuration (from C-plane configuration)

This function adds:

  • DOCA RX queue with O-RAN eCPRI EtherType filtering

  • GPU semaphore setup for packet metadata communication

  • MAC address filtering for RU identification

Parameters:
  • config[inout] Existing EnvConfig (with C-plane settings) to populate with U-plane DOCA RX queue

  • yaml_config[in] Parsed YAML configuration containing RU MAC address

  • uplane_config[in] U-Plane configuration parameters (timing, DOCA settings)

Throws:

std::invalid_argument – if configuration parameters are invalid

struct CellConfig#
#include <fronthaul_parser.hpp>

Per-cell configuration from YAML

Public Members

std::string mac_address#

RU MAC address (eth field)

std::uint16_t vlan_tci = {}#

VLAN TCI (includes PCP in upper bits)

std::vector<std::uint16_t> eaxc_ul#

UL eAxC IDs for antenna ports.

struct DocaOrderSemInfo#
#include <order_kernel_descriptors.hpp>

DOCA semaphore info structure for order kernel.

This structure is passed through DOCA GPUNetIO semaphores to communicate packet metadata from the NIC to the GPU order kernel.

Public Members

std::uint32_t pkts = {}#

Number of packets received.

class Fronthaul : public framework::pipeline::IPipelineOutputProvider#
#include <fronthaul.hpp>

Fronthaul library main class

Manages ORAN fronthaul operations including:

  • Converting FAPI to ORAN C-Plane messages

  • Transmitting C-Plane packets via DPDK

  • Processing U-Plane packets via Order Kernel pipeline

This class is stateless - all timing and request data comes from caller. Use send_ul_cplane() to transmit C-Plane messages for each cell/slot. Use process_uplane() to execute the Order Kernel pipeline.

Implements IPipelineOutputProvider to expose Order Kernel output addresses for zero-copy integration with downstream pipelines.

Public Functions

explicit Fronthaul(const FronthaulConfig &config)#

Construct fronthaul library

Sets up network environment and creates ORAN flows. All setup happens in constructor - ready to use immediately.

Parameters:

config[in] Fronthaul configuration

Throws:
  • std::runtime_error – if setup fails

  • std::invalid_argument – if configuration is invalid

~Fronthaul() override = default#

Destructor

Cleans up resources including CUDA stream if U-Plane was configured.

Fronthaul(const Fronthaul&) = delete#
Fronthaul &operator=(const Fronthaul&) = delete#
Fronthaul(Fronthaul&&) = delete#
Fronthaul &operator=(Fronthaul&&) = delete#
void send_ul_cplane(
const scf_fapi_ul_tti_req_t &request,
std::size_t body_len,
std::uint16_t cell_id,
std::uint64_t absolute_slot,
std::chrono::nanoseconds t0,
std::chrono::nanoseconds tai_offset,
)#

Send uplink C-Plane messages for a cell

Converts FAPI UL_TTI_REQUEST to ORAN C-Plane messages and transmits them. The request must already have sfn and slot fields updated to match the desired transmission timing.

Parameters:
  • request[in] FAPI UL_TTI_REQUEST message with updated timing fields

  • body_len[in] Size of FAPI message request body (excluding body header)

  • cell_id[in] Cell identifier (index into cell_dest_macs)

  • absolute_slot[in] Absolute slot number for timing calculation

  • t0[in] Time for system frame 0, subframe 0, slot 0

  • tai_offset[in] TAI offset for time synchronization

void process_uplane(ran::oran::OranSlotTiming timing)#

Process U-Plane for the current slot

Executes the Order Kernel pipeline to receive and process U-Plane packets. Timing is passed by value to avoid threading issues (U-plane processing is asynchronous).

Parameters:

timing[in] ORAN slot timing (frame, subframe, slot)

inline const FronthaulConfig &config() const noexcept#

Get configuration

Returns:

Reference to fronthaul configuration

FronthaulStats get_stats() const noexcept#

Get fronthaul statistics

Returns:

Current statistics snapshot

void reset_stats() noexcept#

Reset statistics counters to zero

Resets all statistics counters (requests_sent, packets_sent, send_errors) to zero. Useful for test scenarios where fresh statistics are needed.

OrderKernelStatistics read_kernel_statistics() const#

Read accumulated kernel statistics from U-Plane processing

Retrieves accumulated PRB counts across all processed slots.

Throws:

std::runtime_error – if U-Plane is not initialized

Returns:

OrderKernelStatistics with accumulated counts

inline OrderKernelPipeline *get_order_kernel_pipeline(
) const noexcept#

Get Order Kernel pipeline pointer

Provides non-owning access to the Order Kernel pipeline for integration with Driver. The pipeline remains owned by Fronthaul and must not be deleted by the caller.

Returns:

Non-owning pointer to OrderKernelPipeline, or nullptr if U-Plane not initialized

inline virtual std::span<const framework::pipeline::PortInfo> get_order_kernel_outputs(
) const noexcept override#

Get Order Kernel output addresses

Implements IPipelineOutputProvider::get_order_kernel_outputs().

Provides access to the stable output buffer addresses captured after Order Kernel warmup. These addresses can be used for zero-copy data passing to downstream pipelines (e.g., PUSCH pipeline).

The addresses are captured once after Order Kernel initialization and remain valid throughout the Fronthaul lifetime.

Returns:

Span of PortInfo describing Order Kernel outputs, or empty span if U-Plane not initialized

struct OrderKernelStatistics#
#include <fronthaul.hpp>

Order kernel accumulated statistics across all slots

Public Members

std::uint64_t total_pusch_prbs = {}#

Accumulated PUSCH PRBs across all slots.

std::uint64_t total_prach_prbs = {}#

Accumulated PRACH PRBs across all slots.

std::uint64_t total_srs_prbs = {}#

Accumulated SRS PRBs across all slots.

std::uint64_t total_expected_prbs = {}#

Accumulated expected PRBs across all slots.

std::uint64_t slots_processed = {}#

Number of U-Plane slots processed.

struct FronthaulConfig#
#include <fronthaul.hpp>

Configuration for fronthaul library

Public Members

framework::net::EnvConfig net_config = {}#

Network environment configuration.

std::vector<framework::net::MacAddress> cell_dest_macs#

Destination MAC addresses per cell.

std::vector<std::uint16_t> cell_vlan_tcis#

VLAN TCI per cell.

ran::oran::OranNumerology numerology = {ran::oran::from_scs(ran::oran::SubcarrierSpacing::Scs30Khz)}#

ORAN numerology configuration.

std::uint32_t num_antenna_ports = {4}#

Number of antenna ports.

std::uint16_t mtu = {DEFAULT_MTU}#

Maximum transmission unit size.

std::uint32_t slot_ahead = {1}#

Slots to process ahead.

std::uint64_t t1a_max_cp_ul_ns = {}#

T1a max window for uplink C-plane.

std::uint64_t t1a_min_cp_ul_ns = {}#

T1a min window for uplink C-plane.

std::uint64_t tx_cell_start_offset_ns = {0}#

Optional per-cell offset.

std::int64_t gps_alpha = {0}#

GPS alpha timing parameter.

std::int64_t gps_beta = {0}#

GPS beta timing parameter.

UPlaneConfig uplane_config = {}#

U-Plane Order Kernel pipeline configuration.

Public Static Attributes

static constexpr std::uint16_t DEFAULT_MTU = 1514#

Default MTU size in bytes.

struct FronthaulStats#
#include <fronthaul.hpp>

Fronthaul statistics

Note

This struct contains a snapshot of statistics at a point in time. The Fronthaul class maintains atomic counters internally and get_stats() returns a consistent snapshot.

Public Members

std::uint64_t requests_sent = {}#

Total requests sent (one per cell transmission)

std::uint64_t packets_sent = {}#

Total packets transmitted.

std::uint64_t send_errors = {}#

Total send errors encountered.

double avg_packets_per_request = {}#

Average packets per request.

struct FronthaulYamlConfig#
#include <fronthaul_parser.hpp>

Fronthaul configuration parsed from RU emulator YAML

Public Members

std::vector<CellConfig> cells#

Per-cell configuration.

OranTimingConfig timing = {}#

O-RAN timing parameters.

std::uint32_t mtu_size = {}#

MTU size for network config.

struct OranTimingConfig#
#include <fronthaul_parser.hpp>

O-RAN timing parameters from YAML

Note: Timing values in the YAML file are specified in microseconds (µs) and are automatically converted to nanoseconds during parsing.

Public Members

std::uint64_t t1a_max_ns = {}#

T1a max CP UL in nanoseconds.

std::uint64_t t1a_min_ns = {}#

T1a min CP UL in nanoseconds.

struct OrderKernelDynamicDescriptor#
#include <order_kernel_descriptors.hpp>

Dynamic kernel parameters (can change per iteration)

Parameters in this structure are updated every slot/subframe via configure_io(). This includes timing parameters, packet statistics, and timeout configuration.

Strategy: When unsure if a parameter is static or dynamic → make it dynamic (safer).

Public Members

std::uint8_t frame_id = {0}#

Current frame ID (0-255)

std::uint8_t subframe_id = {0}#

Current subframe ID (0-9, 10 subframes per frame)

std::uint8_t slot_id = {0}#

Current slot ID (varies by numerology, e.g., 0-1 for 30kHz SCS)

std::array<std::uint64_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> slot_start = {}#

Slot start time in nanoseconds (system timestamp)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> early_rx_packets = {}#

Early packet count (current slot, GPU writes via GDRCopy)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> on_time_rx_packets = {}#

On-time packet count (current slot)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> late_rx_packets = {}#

Late packet count (current slot)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> next_slot_early_rx_packets = {}#

Early packet count (next slot)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> next_slot_on_time_rx_packets = {}#

On-time packet count (next slot)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> next_slot_late_rx_packets = {}#

Late packet count (next slot)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> rx_packets_dropped_count = {}#

Dropped packet count (always used, even when tracing disabled)

std::array<std::uint64_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> order_kernel_last_timeout_error_time = {}#

Last timeout error timestamp.

class OrderKernelModule : public framework::pipeline::IModule, public framework::pipeline::IAllocationInfoProvider, public framework::pipeline::IGraphNodeProvider, public framework::pipeline::IStreamExecutor#
#include <order_kernel_module.hpp>

OrderKernelModule - ORAN UL Receiver Order Kernel

Wraps the order_kernel_doca_single_subSlot_pingpong CUDA kernel for ORAN packet reception, ordering, and decompression.

Configuration:

  • 1 input port: “doca_objects” (DOCA RX queue parameters, zero-copy)

  • 1 output port: “pusch” (PUSCH IQ data buffer pointer)

  • Custom CUDA kernel for packet processing on GPU

  • GDRCopy memory for NIC↔GPU direct access

Public Functions

explicit OrderKernelModule(
std::string instance_id,
const StaticParams &params,
)#

Construct module with instance ID and parameters

Parameters:
  • instance_id[in] Unique identifier for this module instance

  • params[in] Static configuration parameters

Throws:

gsl::fail_fast – if preconditions are violated

Pre:

params.gdr_handle must not be null

Pre:

params.doca_rxq_params must not be null

~OrderKernelModule() override = default#
OrderKernelModule(const OrderKernelModule&) = delete#
OrderKernelModule &operator=(const OrderKernelModule&) = delete#
OrderKernelModule(OrderKernelModule&&) = delete#
OrderKernelModule &operator=(OrderKernelModule&&) = delete#
inline virtual std::string_view get_type_id() const override#

Get module type identifier

Returns:

Module type string “order_kernel_module”

inline virtual std::string_view get_instance_id() const override#

Get module instance identifier

Returns:

Instance ID provided at construction

virtual framework::pipeline::IStreamExecutor *as_stream_executor(
) override#

Get stream executor interface

Returns:

Pointer to IStreamExecutor interface (this module)

virtual framework::pipeline::IGraphNodeProvider *as_graph_node_provider(
) override#

Get graph node provider interface

Returns:

Pointer to IGraphNodeProvider interface (this module)

virtual std::vector<std::string> get_input_port_names(
) const override#

Get input port names

Returns:

Vector containing “doca_objects”

virtual std::vector<std::string> get_output_port_names(
) const override#

Get output port names

Returns:

Vector containing “pusch”

virtual std::vector<framework::tensor::TensorInfo> get_input_tensor_info(
std::string_view port_name,
) const override#

Get input tensor information for specified port

Parameters:

port_name[in] Input port name

Returns:

Vector of tensor info for the port

virtual std::vector<framework::tensor::TensorInfo> get_output_tensor_info(
std::string_view port_name,
) const override#

Get output tensor information for specified port

Parameters:

port_name[in] Output port name

Returns:

Vector of tensor info for the port

virtual framework::pipeline::InputPortMemoryCharacteristics get_input_memory_characteristics(
std::string_view port_name,
) const override#

Get input memory characteristics for specified port

Parameters:

port_name[in] Input port name

Returns:

Memory characteristics for the port

virtual framework::pipeline::OutputPortMemoryCharacteristics get_output_memory_characteristics(
std::string_view port_name,
) const override#

Get output memory characteristics for specified port

Parameters:

port_name[in] Output port name

Returns:

Memory characteristics for the port

virtual framework::pipeline::ModuleMemoryRequirements get_requirements(
) const override#

Get module memory requirements

Returns:

Memory requirements for descriptors and buffers

virtual void setup_memory(
const framework::pipeline::ModuleMemorySlice &memory_slice,
) override#

Allocate and initialize module memory

Parameters:

memory_slice[in] Memory slice allocated by framework

virtual void set_inputs(
std::span<const framework::pipeline::PortInfo> inputs,
) override#

Configure input port connections.

Parameters:

inputs[in] Input port information containing DOCA objects

virtual void warmup(cudaStream_t stream) override#

Perform warmup operations

Parameters:

stream[in] CUDA stream for warmup operations

virtual void configure_io(
const framework::pipeline::DynamicParams &params,
cudaStream_t stream,
) override#

Configure I/O for current iteration

Parameters:
  • params[in] Dynamic parameters for this iteration

  • stream[in] CUDA stream for async operations during configuration

virtual std::vector<framework::pipeline::PortInfo> get_outputs(
) const override#

Get output port information

Returns:

Vector of output port info

virtual void execute(cudaStream_t stream) override#

Execute kernel in stream mode

Parameters:

stream[in] CUDA stream for kernel execution

virtual std::span<const CUgraphNode> add_node_to_graph(
gsl_lite::not_null<framework::pipeline::IGraph*> graph,
std::span<const CUgraphNode> deps,
) override#

Add order kernel node to CUDA graph.

Parameters:
  • graph[in] Graph interface for node creation

  • deps[in] Dependency nodes that must complete before this node

Returns:

Span of created graph node handle (single order kernel node)

virtual void update_graph_node_params(
CUgraphExec exec,
const framework::pipeline::DynamicParams &params,
) override#

Update graph node parameters

Parameters:
  • exec[in] CUDA graph executable handle

  • params[in] Dynamic parameters for update

OrderKernelResults read_kernel_results() const#

Read kernel execution results from GDRCopy memory

This method reads the kernel results directly from CPU-visible GPU memory without requiring GPU synchronization. Should be called after kernel execution completes.

Returns:

OrderKernelResults structure with current values

struct OrderKernelResults#
#include <order_kernel_module.hpp>

Kernel execution results structure

Public Members

std::uint32_t exit_condition = {}#

Kernel exit condition code.

std::uint32_t pusch_ordered_prbs = {}#

Number of PUSCH PRBs processed.

std::uint32_t prach_ordered_prbs = {}#

Number of PRACH PRBs processed.

std::uint32_t srs_ordered_prbs = {}#

Number of SRS PRBs processed.

std::uint32_t expected_prbs = {}#

Expected total PRBs for this slot.

struct StaticParams#
#include <order_kernel_module.hpp>

Static parameters for module construction

Public Members

framework::pipeline::ExecutionMode execution_mode = {framework::pipeline::ExecutionMode::Stream}#

Pipeline execution mode (default: Stream)

gdr_t gdr_handle = {nullptr}#

Non-owning GDRCopy handle (gdr_t is already a pointer)

const framework::net::DocaRxQParams *doca_rxq_params{nullptr}#

DOCA RX queue parameters (must not be null)

TimingParams timing = {}#

ORAN timing windows (Ta4 early/late thresholds, slot duration)

std::vector<std::uint16_t> eaxc_ids = {0, 1, 2, 3}#

UL eAxC IDs for antenna ports.

struct TimingParams#
#include <order_kernel_module.hpp>

Timing window parameters for ORAN packet processing

These values correspond to the ORAN timing specification and are typically loaded from YAML configuration (Ta4_min_ns, Ta4_max_ns in cuphycontroller config).

Public Members

std::uint64_t slot_duration_ns = {DEFAULT_SLOT_DURATION_NS}#

Slot duration in nanoseconds (default: 500us for 30kHz SCS)

std::uint64_t ta4_min_ns = {DEFAULT_TA4_MIN_NS}#

Ta4 early window - packets before slot_start + ta4_min are early (default: 50us)

std::uint64_t ta4_max_ns = {DEFAULT_TA4_MAX_NS}#

Ta4 late window - packets after slot_start + ta4_max are late (default: 450us)

Public Static Attributes

static constexpr std::uint64_t DEFAULT_SLOT_DURATION_NS = 500'000#

Default slot duration for 30kHz SCS (500 microseconds)

static constexpr std::uint64_t DEFAULT_TA4_MIN_NS = 50'000#

Default Ta4 early window (50 microseconds)

static constexpr std::uint64_t DEFAULT_TA4_MAX_NS = 450'000#

Default Ta4 late window (450 microseconds)

class OrderKernelModuleFactory : public framework::pipeline::IModuleFactory#
#include <order_kernel_factories.hpp>

Factory for creating OrderKernelModule instances

Creates modules of type “order_kernel_module” using the factory pattern.

Public Functions

OrderKernelModuleFactory() = default#
~OrderKernelModuleFactory() override = default#
OrderKernelModuleFactory(const OrderKernelModuleFactory&) = delete#
OrderKernelModuleFactory &operator=(
const OrderKernelModuleFactory&,
) = delete#
OrderKernelModuleFactory(OrderKernelModuleFactory&&) = default#

Move constructor

OrderKernelModuleFactory &operator=(
OrderKernelModuleFactory&&,
) = default#

Move assignment operator

Returns:

Reference to this object

virtual std::unique_ptr<framework::pipeline::IModule> create_module(
std::string_view module_type,
const std::string &instance_id,
const std::any &static_params,
) override#

Create an OrderKernelModule instance

Parameters:
  • module_type[in] Module type identifier (must be “order_kernel_module”)

  • instance_id[in] Unique instance identifier

  • static_params[in] Static parameters (OrderKernelModule::StaticParams)

Throws:
  • std::invalid_argument – if module_type is not supported

  • std::bad_any_cast – if static_params has wrong type

Returns:

Unique pointer to created module

virtual bool supports_module_type(
std::string_view module_type,
) const override#

Check if factory supports the given module type

Parameters:

module_type[in] Module type to check

Returns:

true if module_type is “order_kernel_module”

std::unique_ptr<ran::fronthaul::OrderKernelModule> create_order_kernel_module(
const std::string &instance_id,
const std::any &static_params,
)#

Create an OrderKernelModule instance with specific return type

Convenience method that returns the specific module type without requiring a cast. This is a non-virtual wrapper around the virtual create_module() method.

Parameters:
Throws:

std::bad_any_cast – if static_params has wrong type

Returns:

Unique pointer to created OrderKernelModule

class OrderKernelPipeline : public framework::pipeline::IPipeline#
#include <order_kernel_pipeline.hpp>

OrderKernelPipeline - ORAN UL Receiver Pipeline

Single-module pipeline for ORAN packet reception and processing:

  • External Input (DOCA objects) ─→ OrderKernelModule ─→ External Output (PUSCH data)

Features:

  • Single OrderKernelModule wrapping order_kernel_doca_single_subSlot_pingpong

  • Stream and graph execution modes

  • GDRCopy memory management for NIC↔GPU communication

  • External DOCA input handling

Public Functions

OrderKernelPipeline(
std::string pipeline_id,
std::unique_ptr<framework::pipeline::IModuleFactory> module_factory,
const framework::pipeline::PipelineSpec &spec,
const framework::net::DocaRxQParams *doca_rxq_params,
)#

Construct OrderKernelPipeline using factory pattern

Creates the OrderKernelModule via the provided factory and configures the pipeline according to the PipelineSpec.

Parameters:
  • pipeline_id[in] Unique identifier for pipeline instance

  • module_factory[in] Factory for creating modules (takes ownership)

  • spec[in] Pipeline specification with module configuration

  • doca_rxq_params[in] DOCA RX queue parameters (non-owning pointer, must outlive pipeline)

Throws:
  • std::invalid_argument – if spec doesn’t have exactly 1 module or doca_rxq_params is null

  • std::runtime_error – if module creation fails or GDRCopy init fails

~OrderKernelPipeline() override = default#
OrderKernelPipeline(const OrderKernelPipeline&) = delete#
OrderKernelPipeline &operator=(const OrderKernelPipeline&) = delete#
OrderKernelPipeline(OrderKernelPipeline&&) = delete#
OrderKernelPipeline &operator=(OrderKernelPipeline&&) = delete#
inline virtual std::string_view get_pipeline_id() const override#

Get pipeline identifier

Returns:

Pipeline ID string

inline virtual std::size_t get_num_external_inputs() const override#

Get number of external inputs

Returns:

Number of external inputs (1 for DOCA objects)

inline virtual std::size_t get_num_external_outputs() const override#

Get number of external outputs

Returns:

Number of external outputs (1 for PUSCH buffer)

virtual std::vector<framework::pipeline::PortInfo> get_outputs(
) const override#

Get pipeline output port information

Provides access to Order Kernel’s output buffer addresses. These addresses are stable after warmup() and can be used for zero-copy data passing to downstream pipelines (e.g., PUSCH).

Throws:

std::runtime_error – if module not initialized

Returns:

Vector containing one PortInfo with PUSCH buffer information

virtual void setup() override#

Perform pipeline setup

Allocates memory and initializes all modules

virtual void warmup(cudaStream_t stream) override#

Perform warmup operations

Parameters:

stream[in] CUDA stream for warmup operations

virtual void configure_io(
const framework::pipeline::DynamicParams &params,
std::span<const framework::pipeline::PortInfo> external_inputs,
std::span<framework::pipeline::PortInfo> external_outputs,
cudaStream_t stream,
) override#

Configure pipeline I/O for the current iteration.

Parameters:
  • params[in] Dynamic parameters for this iteration

  • external_inputs[in] External input port information (DOCA objects)

  • external_outputs[out] External output port information to populate

  • stream[in] CUDA stream for any necessary operations

virtual void execute_stream(cudaStream_t stream) override#

Execute pipeline in stream mode

Parameters:

stream[in] CUDA stream for execution

virtual void execute_graph(cudaStream_t stream) override#

Execute pipeline in graph mode

Parameters:

stream[in] CUDA stream for graph execution

OrderKernelModule::OrderKernelResults read_kernel_results() const#

Read kernel execution results from the OrderKernelModule

This method provides access to kernel results including exit condition and PRB counts. Should be called after kernel execution completes.

Throws:

std::runtime_error – if module is not available or not an OrderKernelModule

Returns:

OrderKernelModule::OrderKernelResults structure with current values

class OrderKernelPipelineFactory : public framework::pipeline::IPipelineFactory#
#include <order_kernel_factories.hpp>

Factory for creating OrderKernelPipeline instances

Creates pipelines of type “order_kernel_pipeline” using the factory pattern. Each pipeline gets its own dedicated OrderKernelModuleFactory instance.

Public Functions

OrderKernelPipelineFactory() = default#
~OrderKernelPipelineFactory() override = default#
OrderKernelPipelineFactory(const OrderKernelPipelineFactory&) = delete#
OrderKernelPipelineFactory &operator=(
const OrderKernelPipelineFactory&,
) = delete#
OrderKernelPipelineFactory(OrderKernelPipelineFactory&&) = default#

Move constructor

OrderKernelPipelineFactory &operator=(
OrderKernelPipelineFactory&&,
) = default#

Move assignment operator

Returns:

Reference to this object

virtual std::unique_ptr<framework::pipeline::IPipeline> create_pipeline(
std::string_view pipeline_type,
const std::string &pipeline_id,
const framework::pipeline::PipelineSpec &spec,
) override#

Create an OrderKernelPipeline instance

Parameters:
  • pipeline_type[in] Pipeline type identifier (must be “order_kernel_pipeline”)

  • pipeline_id[in] Unique pipeline identifier

  • spec[in] Pipeline specification

Throws:

std::invalid_argument – if pipeline_type is not supported or spec is invalid

Returns:

Unique pointer to created pipeline

virtual bool is_pipeline_type_supported(
std::string_view pipeline_type,
) const override#

Check if factory supports the given pipeline type

Parameters:

pipeline_type[in] Pipeline type to check

Returns:

true if pipeline_type is “order_kernel_pipeline”

virtual std::vector<std::string> get_supported_pipeline_types(
) const override#

Get list of supported pipeline types

Returns:

Vector containing “order_kernel_pipeline”

inline void set_doca_params(
const framework::net::DocaRxQParams *doca_params,
) noexcept#

Set DOCA RX queue parameters for pipeline creation

Must be called before create_pipeline() to provide infrastructure handles.

Parameters:

doca_params[in] DOCA RX queue parameters (non-owning pointer, must outlive factory)

std::unique_ptr<ran::fronthaul::OrderKernelPipeline> create_order_kernel_pipeline(
const std::string &pipeline_id,
const framework::pipeline::PipelineSpec &spec,
)#

Create an OrderKernelPipeline instance with specific return type

Convenience method that returns the specific pipeline type without requiring a cast. This is a non-virtual wrapper around the virtual create_pipeline() method.

Parameters:
  • pipeline_id[in] Unique pipeline identifier

  • spec[in] Pipeline specification

Throws:

std::runtime_error – if DOCA params not set or pipeline creation fails

Returns:

Unique pointer to created OrderKernelPipeline

struct OrderKernelStaticDescriptor#
#include <order_kernel_descriptors.hpp>

Static kernel parameters (set once during setup)

Parameters in this structure are initialized during module setup and remain constant throughout the pipeline’s lifetime. This includes DOCA objects, cell configuration, buffer pointers, and GDRCopy device addresses.

Based on OrderKernelConfigParamsT from test_oran_order_kernel.cpp

Public Members

std::array<doca_gpu_eth_rxq*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> rxq_info_gpu = {}#

DOCA RX queue device pointers (from DOCA GPUNetIO)

std::array<doca_gpu_semaphore_gpu*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> sem_gpu = {}#

DOCA semaphore GPU objects for packet ordering.

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> sem_order_num = {}#

Semaphore item count (must be power of 2)

std::array<int, ORDER_KERNEL_MAX_CELLS_PER_SLOT> cell_id = {}#

Cell identifier (0 for single-cell)

std::array<int, ORDER_KERNEL_MAX_CELLS_PER_SLOT> comp_meth = {}#

Compression method (1=BFP)

std::array<int, ORDER_KERNEL_MAX_CELLS_PER_SLOT> bit_width = {}#

BFP bit width (14 for BFP14)

std::array<int, ORDER_KERNEL_MAX_CELLS_PER_SLOT> ru_type = {}#

RU type (2=FXCN O-RU specific handling)

std::array<float, ORDER_KERNEL_MAX_CELLS_PER_SLOT> beta = {}#

Beta scaling factor for BFP decompression (0.000244 for BFP14)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> start_cuphy_d = {}#

PHY start signal (CPU → GPU via GDRCopy)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> order_kernel_exit_cond_d = {}#

Kernel exit condition status (GPU → CPU via GDRCopy)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> last_sem_idx_rx_h = {}#

Last RX semaphore index (device memory)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> last_sem_idx_order_h = {}#

Last order semaphore index (device memory)

std::array<std::uint16_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pusch_e_ax_c_map = {}#

Antenna port (eAxC ID) mapping (GDRCopy-backed)

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pusch_e_ax_c_num = {}#

Number of antenna ports (4 for 4x4 MIMO)

std::array<std::uint8_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pusch_buffer = {}#

PUSCH output buffer (device memory)

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pusch_prb_x_slot = {}#

PRBs per slot (273 for 100MHz bandwidth)

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pusch_prb_x_symbol = {}#

PRBs per symbol.

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pusch_prb_x_symbol_x_antenna = {}#

PRBs per symbol per antenna.

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pusch_prb_stride = {}#

PRB stride in bytes (273 * 48 bytes for 100MHz BW)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pusch_ordered_prbs = {}#

Ordered PRB counter (GDRCopy-backed for CPU visibility)

std::array<std::uint16_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_e_ax_c_map = {}#

PRACH antenna port mapping (GDRCopy-backed)

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_e_ax_c_num = {}#

Number of PRACH antenna ports.

std::array<std::uint8_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_buffer_0 = {}#

PRACH FDM occasion 0 buffer.

std::array<std::uint8_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_buffer_1 = {}#

PRACH FDM occasion 1 buffer.

std::array<std::uint8_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_buffer_2 = {}#

PRACH FDM occasion 2 buffer.

std::array<std::uint8_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_buffer_3 = {}#

PRACH FDM occasion 3 buffer.

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_prb_x_slot = {}#

PRACH PRBs per slot.

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_prb_x_symbol = {}#

PRACH PRBs per symbol.

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_prb_x_symbol_x_antenna = {}#

PRACH PRBs per symbol per antenna.

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_prb_stride = {}#

PRACH PRB stride in bytes.

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> prach_ordered_prbs = {}#

PRACH ordered PRB counter (GDRCopy-backed)

std::array<std::uint16_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> srs_e_ax_c_map = {}#

SRS antenna port mapping (GDRCopy-backed)

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> srs_e_ax_c_num = {}#

Number of SRS antenna ports.

std::array<std::uint8_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> srs_buffer = {}#

SRS output buffer.

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> srs_prb_x_slot = {}#

SRS PRBs per slot.

std::array<std::uint32_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> srs_prb_stride = {}#

SRS PRB stride in bytes.

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> srs_ordered_prbs = {}#

SRS ordered PRB counter (GDRCopy-backed)

std::array<std::uint8_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> srs_start_sym = {}#

SRS start symbol index.

std::uint32_t *sym_ord_done_sig_arr = {nullptr}#

Symbol ordering done signal array.

std::uint32_t *sym_ord_done_mask_arr = {nullptr}#

Symbol ordering done mask array.

std::uint32_t *pusch_prb_symbol_map_d = {nullptr}#

PUSCH PRB-to-symbol mapping.

std::uint32_t *num_order_cells_sym_mask_arr = {nullptr}#

Number of order cells symbol mask array.

std::array<std::uint64_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> ta4_min_ns = {}#

Early packet threshold (Ta4_min in ORAN spec, nanoseconds)

std::array<std::uint64_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> ta4_max_ns = {}#

Late packet threshold (Ta4_max in ORAN spec, nanoseconds)

std::array<std::uint64_t, ORDER_KERNEL_MAX_CELLS_PER_SLOT> slot_duration = {}#

Slot duration in nanoseconds (e.g., 500us for 30kHz SCS)

std::uint64_t timeout_no_pkt_ns = {DEFAULT_TIMEOUT_NO_PKT_NS}#

Timeout if no packets received (nanoseconds, default 6 seconds)

std::uint64_t timeout_first_pkt_ns = {DEFAULT_TIMEOUT_FIRST_PKT_NS}#

Timeout for first packet (nanoseconds, default 1500 microseconds)

std::uint64_t timeout_log_interval_ns = {DEFAULT_TIMEOUT_LOG_INTERVAL_NS}#

Log interval for timeout messages (nanoseconds, default 1 second)

std::uint8_t timeout_log_enable = {DEFAULT_TIMEOUT_LOG_ENABLE}#

Enable timeout logging (1=enable, 0=disable)

std::uint32_t max_rx_pkts = {DEFAULT_MAX_RX_PKTS}#

Maximum packets to receive per call (default 100)

std::uint64_t rx_pkts_timeout_ns = {DEFAULT_RX_PKTS_TIMEOUT_NS}#

RX packet timeout (nanoseconds, default 100 microseconds)

std::array<std::uint64_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> rx_packets_ts = {}#

Packet timestamps per symbol.

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> rx_packets_count = {}#

Packet counts per symbol.

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> rx_bytes_count = {}#

Byte counts per symbol.

std::array<std::uint64_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> rx_packets_ts_earliest = {}#

Earliest packet timestamp.

std::array<std::uint64_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> rx_packets_ts_latest = {}#

Latest packet timestamp.

std::array<std::uint64_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> next_slot_rx_packets_ts = {}#

Next slot packet timestamps.

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> next_slot_rx_packets_count = {}#

Next slot packet counts.

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> next_slot_rx_bytes_count = {}#

Next slot byte counts.

std::array<std::uint8_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pcap_buffer = {}#

PCAP capture buffer.

std::array<std::uint8_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pcap_buffer_ts = {}#

PCAP timestamp buffer.

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> pcap_buffer_index = {}#

PCAP buffer index.

int *barrier_flag = {nullptr}#

Barrier flag for synchronization (Phase 2)

std::array<std::uint8_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> done_shared = {}#

Completion flag (Phase 2)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> next_slot_num_prb_ch1 = {}#

Next slot PRB count channel 1 (Phase 2)

std::array<std::uint32_t*, ORDER_KERNEL_MAX_CELLS_PER_SLOT> next_slot_num_prb_ch2 = {}#

Next slot PRB count channel 2 (Phase 2)

struct PacketSendTimeParams#
#include <fronthaul.hpp>

Packet send time calculation input parameters

Public Members

std::chrono::nanoseconds t0 = {}#

Time for system frame 0, subframe 0, slot 0.

std::chrono::nanoseconds tai_offset = {}#

TAI offset for time synchronization.

std::uint64_t absolute_slot = {}#

Absolute slot number being processed.

std::chrono::nanoseconds slot_period = {}#

Slot period.

std::uint32_t slot_ahead = {}#

Number of slots processing is ahead of real-time.

std::chrono::nanoseconds t1a_max_cp_ul = {}#

T1a max window for uplink C-plane.

std::chrono::nanoseconds actual_start = {}#

Actual processing start time (current time)

struct PacketSendTimeResult#
#include <fronthaul.hpp>

Packet send time calculation result

Public Members

std::chrono::nanoseconds expected_start = {}#

Expected slot start time.

std::chrono::nanoseconds actual_start = {}#

Actual processing start time.

std::chrono::nanoseconds time_delta = {}#

Delta between actual and expected.

std::chrono::nanoseconds threshold = {}#

Timing threshold.

std::chrono::nanoseconds start_tx = {}#

Calculated packet transmission time.

bool exceeds_threshold = {}#

True if delta exceeds threshold.

struct UPlaneConfig#
#include <uplane_config.hpp>

U-Plane configuration parameters

Configuration for ORAN U-Plane packet reception using Order Kernel pipeline. Default values are suitable for 30kHz SCS (500us slot duration) in production environments.

Public Members

std::uint64_t ta4_min_ns = {50'000}#

Ta4 early window (50us before slot start)

std::uint64_t ta4_max_ns = {450'000}#

Ta4 late window (450us after slot start)

std::uint64_t slot_duration_ns = {500'000}#

Slot duration (500us for 30kHz SCS)

std::uint64_t timeout_no_pkt_ns = {DEFAULT_TIMEOUT_NO_PKT_NS}#

Timeout with no packets (default: 6s)

std::uint64_t timeout_first_pkt_ns = {DEFAULT_TIMEOUT_FIRST_PKT_NS}#

Timeout for first packet (default: 1500us)

std::uint64_t timeout_log_interval_ns = {DEFAULT_TIMEOUT_LOG_INTERVAL_NS}#

Timeout log interval (default: 1s)

bool timeout_log_enable = {true}#

Enable timeout logging.

std::uint32_t max_rx_pkts = {DEFAULT_MAX_RX_PKTS}#

Maximum RX packets to process per iteration (default: 512)

std::uint64_t rx_pkts_timeout_ns = {DEFAULT_RX_PKTS_TIMEOUT_NS}#

RX packet timeout (default: 100us)

std::uint32_t num_packets = {16384}#

Number of packet buffers in RX queue (16K)

std::uint32_t max_packet_size = {8192}#

Maximum packet size (8KB, observed 1494 bytes in production)

std::uint32_t gpu_semaphore_items = {4096}#

GPU semaphore items (4096, must be power of 2)

std::vector<std::uint16_t> eaxc_ids = {0, 1, 2, 3}#

UL eAxC IDs for antenna ports (default: [0, 1, 2, 3])