ORAN#

O-RAN fronthaul control plane message processing and numerology calculations for 5G NR radio access networks.

Overview#

The ORAN library provides C-plane (control plane) message creation and numerology calculations for O-RAN fronthaul interfaces. It handles 3GPP TS 38.211 compliant timing parameter calculations, C-plane message construction with section fragmentation, and packet buffer management.

Key Features#

  • Numerology Calculations: Timing parameter calculations from subcarrier spacing (slots per subframe, slot period, symbol duration)

  • C-Plane Messages: Control plane message construction with automatic section fragmentation across MTU boundaries

  • Buffer Abstraction: Interface enabling both production DPDK mbufs and lightweight vector-based buffers for testing without DPDK initialization

  • Packet Generation: eCPRI packet creation with sequence ID and timestamp management

Core Concepts#

Numerology#

OranNumerology encapsulates 3GPP timing parameters derived from subcarrier spacing (SCS). The numerology determines slots per subframe, slot period, and symbol duration based on the configured SCS.

Basic Numerology and Timing#

// Create numerology from subcarrier spacing
const auto numerology = ran::oran::from_scs(ran::oran::SubcarrierSpacing::Scs30Khz);

// Access timing parameters derived from SCS
const auto scs = numerology.subcarrier_spacing;
const auto slots = numerology.slots_per_subframe; // 30 kHz SCS = 2 slots per 1ms subframe

Slot Timing Calculations#

const auto numerology = ran::oran::from_scs(ran::oran::SubcarrierSpacing::Scs30Khz);

// Calculate timing for absolute slot number
constexpr std::uint64_t ABSOLUTE_SLOT = 100;
const auto timing = numerology.calculate_slot_timing(ABSOLUTE_SLOT);

// Timing decomposed into frame, subframe, and slot
const auto frame = timing.frame_id;
const auto subframe = timing.subframe_id;
const auto slot = timing.slot_id;

Subcarrier Spacing Conversion#

// Convert from kHz value
const auto scs = ran::oran::from_khz(60);

// Convert to kHz value
const auto khz = ran::oran::to_khz(ran::oran::SubcarrierSpacing::Scs60Khz);

Slot Timestamps#

const auto numerology = ran::oran::from_scs(ran::oran::SubcarrierSpacing::Scs30Khz);

// Create timing for frame 10, subframe 5, slot 1
ran::oran::OranSlotTiming timing{};
timing.frame_id = 10;
timing.subframe_id = 5;
timing.slot_id = 1;

// Calculate absolute timestamp in nanoseconds
const auto timestamp_ns = numerology.calculate_slot_timestamp(timing);

Timestamps are calculated as nanoseconds since System Frame Number (SFN) 0, slot 0, enabling precise timing alignment across the radio access network.

C-Plane Messages#

OranCPlaneMsgInfo structures define control plane messages with sections describing resource block allocations, beam IDs, and symbol timing. Messages support multiple section types (0, 1, 3, 5) and optional section extensions.

Basic C-Plane Message#

// Create message info structure
ran::oran::OranCPlaneMsgInfo msg_info{};

// Set up radio application header
auto &radio_hdr = msg_info.section_common_hdr.sect_1_common_hdr.radioAppHdr;
radio_hdr.frameId = 10;
radio_hdr.subframeId = 5;
radio_hdr.slotId = 3;
radio_hdr.startSymbolId = 0;
radio_hdr.numberOfSections = 1;
radio_hdr.sectionType = ORAN_CMSG_SECTION_TYPE_1;
radio_hdr.dataDirection = DIRECTION_DOWNLINK;

// Configure message properties
msg_info.data_direction = DIRECTION_DOWNLINK;
msg_info.num_sections = 1;
msg_info.tx_window_start = 1000000ULL;

// Configure section
auto &section = msg_info.sections.at(0);
section.sect_1.sectionId = 1;
section.sect_1.startPrbc = 0;
section.sect_1.numPrbc = 10;
section.sect_1.beamId = 0;

Packet Creation#

// Create message information
ran::oran::OranCPlaneMsgInfo msg_info{};
msg_info.section_common_hdr.sect_1_common_hdr.radioAppHdr.sectionType =
        ORAN_CMSG_SECTION_TYPE_1;
msg_info.section_common_hdr.sect_1_common_hdr.radioAppHdr.numberOfSections = 1;
msg_info.section_common_hdr.sect_1_common_hdr.radioAppHdr.dataDirection = DIRECTION_DOWNLINK;
msg_info.data_direction = DIRECTION_DOWNLINK;
msg_info.num_sections = 1;

// Set up flow and peer for packet generation
ran::oran::PacketHeaderTemplate header_template{};
header_template.ecpri.ecpriVersion = ORAN_DEF_ECPRI_VERSION;
header_template.ecpri.ecpriMessage = ECPRI_MSG_TYPE_RTC;

ran::oran::SimpleOranFlow flow(header_template);
ran::oran::SimpleOranPeer peer;

// Allocate output buffers
std::vector<ran::oran::VecBuf> buffers(5, ran::oran::VecBuf(1500));
constexpr std::uint16_t MTU = 1500;

// Create C-plane packets
const auto packet_count = ran::oran::prepare_cplane_message(
        msg_info, flow, peer, std::span<ran::oran::VecBuf>{buffers}, MTU);

The prepare_cplane_message function automatically handles MTU-based fragmentation, splitting large messages across multiple packets when sections exceed the configured maximum transmission unit.

Packet Counting#

// Create message information
ran::oran::OranCPlaneMsgInfo msg_info{};
msg_info.section_common_hdr.sect_1_common_hdr.radioAppHdr.sectionType =
        ORAN_CMSG_SECTION_TYPE_1;
msg_info.section_common_hdr.sect_1_common_hdr.radioAppHdr.numberOfSections = 5;
msg_info.num_sections = 5;

// Predict packet count before allocation
std::array<ran::oran::OranCPlaneMsgInfo, 1> messages = {msg_info};
constexpr std::uint16_t MTU = 1500;

const auto predicted_count = ran::oran::count_cplane_packets(messages, MTU);

Use count_cplane_packets to predict buffer requirements before message preparation.

Buffer Abstraction#

OranBuf provides an abstract interface enabling packet preparation code to work with different buffer implementations without modification. This design allows testing with simple vector-based buffers while using high-performance DPDK mbufs in production.

The abstraction serves two key purposes:

  1. Testing Without DPDK: Unit tests can use VecBuf (std::vector-based) to verify packet construction logic without requiring DPDK initialization, which needs network hardware and elevated privileges

  2. Production Performance: MBuf wraps DPDK mbufs for zero-copy packet transmission in production deployments

VecBuf Usage#

// Create a vector-based buffer
constexpr std::size_t BUFFER_SIZE = 1500;
ran::oran::VecBuf buffer(BUFFER_SIZE);

// Access buffer properties
const auto capacity = buffer.capacity();
const auto initial_size = buffer.size();

// Set data size
buffer.set_size(100);
const auto new_size = buffer.size();

// Access buffer data
auto *data_ptr = buffer.data();

Accurate Send Scheduling#

// Wrap DPDK mbuf for ORAN packet transmission
ran::oran::MBuf buffer(test_mbuf_);

// Get current time in nanoseconds since epoch
const auto now = system_clock::now().time_since_epoch();
const auto ns = duration_cast<nanoseconds>(now).count();
const auto current_time_ns = static_cast<std::uint64_t>(ns);

// Set timestamp for hardware-assisted send scheduling
// Timestamp specifies when NIC should transmit the packet
buffer.set_timestamp(current_time_ns);

The MBuf implementation supports timestamp metadata for accurate send scheduling using NIC hardware timestamping. This ensures packets are sent at precise timings required for O-RAN control plane messages to the Radio Unit (RU), which demand nanosecond precision. The set_timestamp method automatically configures the DPDK mbuf dynfield timestamp and sets the TX_TIMESTAMP offload flag, enabling hardware-assisted packet transmission at the specified time.

Additional Examples#

For more examples, see:

  • ran/runtime/oran/tests/oran_sample_tests.cpp - Documentation examples and basic usage patterns

API Reference#

enum class ran::oran::SubcarrierSpacing : std::uint32_t#

Subcarrier spacing values (3GPP TS 38.211)

Values:

enumerator Scs15Khz#

15 kHz subcarrier spacing

enumerator Scs30Khz#

30 kHz subcarrier spacing

enumerator Scs60Khz#

60 kHz subcarrier spacing

enumerator Scs120Khz#

120 kHz subcarrier spacing

enum class ran::oran::OranErrc : std::uint8_t#

ORAN framework error codes compatible with std::error_code

This enum class provides type-safe error codes for ORAN operations that integrate seamlessly with the standard C++ error handling framework.

Values:

enumerator Success#

Operation succeeded.

enumerator UnsupportedSectionType#

Section type is not supported.

enumerator SectionExtensionsNotSupported#

Section extensions not supported for this section type.

enumerator MultipleExtensionsNotSupported#

Multiple extensions in a single section are not yet supported.

enumerator MtuTooSmallForExt11#

MTU too small to hold a section with extType 11 bundle.

enumerator MtuTooSmallForSection#

MTU too small for section header.

enumerator Ext11BundlesNotInitialized#

Extension type 11 bundles data not initialized.

enumerator Ext11BfwIqNotInitialized#

Extension type 11 BFW IQ data not initialized.

enumerator Ext11BfwIqSizeNotSet#

Extension type 11 BFW IQ size not set.

enumerator Ext11BundleBfwIqNotInitialized#

Extension type 11 bundle BFW IQ data not initialized.

enumerator InvalidBufferArray#

Invalid buffer array provided.

enumerator MtuCannotBeZero#

MTU cannot be zero.

enumerator MtuTooSmallForSingleSection#

MTU too small for even a single section.

enumerator InsufficientBuffers#

Insufficient buffers for packet fragmentation.

enumerator BundleIndexOutOfBounds#

Bundle index out of bounds.

enumerator InvalidPrbAllocationRbSizeZero#

Invalid PRB allocation: rb_size is zero.

enumerator InvalidPrbAllocationNumSymbolsZero#

Invalid PRB allocation: num_of_symbols is zero.

enumerator InvalidPrbAllocationExceedsSlot#

Invalid PRB allocation: symbol allocation exceeds slot boundary.

enumerator TooManySectionsForSymbol#

Too many sections for start symbol (exceeds MAX_CPLANE_SECTIONS)

enumerator TooManyPdus#

Too many PDUs (exceeds maximum)

enumerator InvalidNumAntennaPorts#

Number of antenna ports cannot be zero.

enumerator PduPayloadOutOfBounds#

PDU parsing exceeded payload bounds.

constexpr std::size_t ran::oran::MAX_CPLANE_SECTIONS = 64#

Maximum number of sections per C-plane message.

constexpr std::size_t ran::oran::MAX_PRB_CHUNKS = 255#

Maximum PRB chunks capacity.

constexpr std::uint32_t ran::oran::SUBFRAMES_PER_FRAME = 10#

Subframes per frame.

constexpr std::uint64_t ran::oran::SUBFRAME_NS = 1'000'000#

Subframe period in ns (1ms)

constexpr std::uint64_t ran::oran::FRAME_PERIOD_NS = SUBFRAME_NS * SUBFRAMES_PER_FRAME#

Frame period in ns (10ms)

constexpr std::uint64_t ran::oran::SFN_MAX = 1024LL#

System Frame Number maximum value.

constexpr std::uint64_t ran::oran::SFN_PERIOD_NS = SFN_MAX * FRAME_PERIOD_NS#

SFN rollover period in ns.

template<std::derived_from<OranBuf> BufferType, std::size_t EXTENT = std::dynamic_extent>
std::uint16_t ran::oran::prepare_cplane_message(
OranCPlaneMsgInfo &info,
OranFlow &flow,
OranPeer &peer,
std::span<BufferType, EXTENT> buffers,
std::uint16_t mtu,
)#

Prepare C-plane message packets

Creates C-plane packets from message information, handling fragmentation across multiple packets when sections don’t fit in MTU.

Template Parameters:
  • BufferType – Type derived from OranBuf

  • Extent – Span extent (static or dynamic)

Parameters:
  • info[inout] Message information containing sections and headers

  • flow[inout] Flow interface for packet templates and sequence IDs

  • peer[inout] Peer interface for timestamp tracking

  • buffers[inout] Span of buffer objects to fill

  • mtu[in] Maximum transmission unit size in bytes

Returns:

Number of packets created

std::size_t ran::oran::count_cplane_packets(
std::span<OranCPlaneMsgInfo> infos,
std::uint16_t mtu,
)#

Count required C-plane packets

Calculates how many packets will be needed to send the given C-plane messages, accounting for MTU limitations and section fragmentation.

Parameters:
  • infos[inout] Span of message information structures

  • mtu[in] Maximum transmission unit size in bytes

Returns:

Total number of packets needed

inline std::uint16_t ran::oran::cpu_to_be_16(
const std::uint16_t value,
)#

Convert CPU byte order to big endian (network byte order)

Parameters:

value[in] Value in CPU byte order

Returns:

Value in big endian byte order

inline std::uint64_t ran::oran::cpu_to_be_64(std::uint64_t value)#

Convert CPU byte order to big endian (network byte order) for 64-bit values

Parameters:

value[in] Value in CPU byte order

Returns:

Value in big endian byte order

std::uint16_t ran::oran::get_cmsg_common_hdr_size(
std::uint8_t section_type,
)#

Get C-plane message common header size for section type

Parameters:

section_type[in] Section type (0, 1, 3, 5)

Throws:

std::invalid_argument – if section_type is out of bounds or unsupported

Returns:

Size of common header in bytes

std::uint16_t ran::oran::get_cmsg_section_size(
std::uint8_t section_type,
)#

Get C-plane message section size for section type

Parameters:

section_type[in] Section type (0, 1, 3, 5)

Throws:

std::invalid_argument – if section_type is out of bounds or unsupported

Returns:

Size of section in bytes

std::error_code ran::oran::find_contiguous_prb_chunks(
const scf_fapi_ul_tti_req_t &request,
std::size_t body_len,
PrbChunks &output,
)#

Aggregates contiguous PRBs from PUSCH PDUs in an UL_TTI.request

PRBs are considered contiguous and merged into a single chunk if they:

  1. Have the same start symbol index (start_symbol_index)

  2. Have the same number of symbols (num_of_symbols)

  3. Are adjacent in frequency (rb_start + rb_size of one equals rb_start of next)

The function extracts PRB allocation information from all PUSCH PDUs in the request, sorts them by start symbol and frequency, then merges adjacent allocations with matching symbol ranges. Multiple chunks may share the same start symbol if they have different num_of_symbols or are non-contiguous in frequency.

The function also validates that for each start_symbol_index, the total number of sections needed does not exceed MAX_CPLANE_SECTIONS (64). If the limit is exceeded, an error is logged and the function returns an error code. The output chunks vector is cleared before processing.

Parameters:
  • request[in] UL_TTI.request containing PUSCH PDUs

  • body_len[in] Length of message body (from FAPI body_hdr.length or equivalent)

  • output[out] Aggregated PRB chunks (cleared before use)

Return values:
  • OranErrc::Success – Operation completed successfully

  • OranErrc::InvalidPrbAllocationRbSizeZero – PRB allocation has zero rb_size

  • OranErrc::invalid_prb_allocation_num_symbols_zero – PRB allocation has zero num_of_symbols

  • OranErrc::invalid_prb_allocation_exceeds_slot – Symbol allocation exceeds slot boundary

  • OranErrc::too_many_sections_for_symbol – Section limit exceeded for a start symbol

  • OranErrc::PduPayloadOutOfBounds – PDU parsing exceeded payload bounds

Returns:

Error code indicating success or specific error condition

std::error_code ran::oran::convert_prb_chunks_to_cplane(
const PrbChunks &chunks,
const OranSlotTiming &slot_timing,
std::uint16_t num_antenna_ports,
const OranTxWindows &tx_windows,
const OranNumerology &numerology,
std::vector<OranCPlaneMsgInfo> &msg_infos,
)#

Convert PRB chunks to C-plane message infos

Converts PRB chunks to ORAN C-plane Section Type 1 messages. Chunks are grouped by their start_symbol_index, and each group is converted to one message per antenna port. Within a message, each chunk becomes one or more sections:

  • Multiple non-contiguous chunks with the same start_symbol_index become multiple sections in the same message

  • Each section within a message can have different num_of_symbols

  • Large chunks (>255 PRBs) are split into multiple sections

The input chunks should already be validated by find_contiguous_prb_chunks to ensure section limits are not exceeded.

Creates messages for antenna port 0 first, then duplicates for other antenna ports.

Parameters:
  • chunks[in] PRB chunks to convert (must be sorted by start_symbol_index and validated)

  • slot_timing[in] Slot timing information (frame, subframe, slot)

  • num_antenna_ports[in] Number of antenna ports in system

  • tx_windows[in] Base transmission timing windows (for symbol 0)

  • numerology[in] ORAN numerology parameters

  • msg_infos[inout] Vector to append C-plane messages to (not cleared)

Return values:
  • OranErrc::Success – Operation completed successfully

  • OranErrc::invalid_num_antenna_ports – Number of antenna ports is zero

  • OranErrc::InvalidPrbAllocationRbSizeZero – PRB chunk has zero rb_size

  • OranErrc::invalid_prb_allocation_num_symbols_zero – PRB chunk has zero num_of_symbols

  • OranErrc::invalid_prb_allocation_exceeds_slot – Symbol allocation exceeds slot boundary

Returns:

Error code indicating success or specific error condition

std::error_code ran::oran::convert_ul_tti_request_to_cplane(
const scf_fapi_ul_tti_req_t &request,
std::size_t body_len,
std::uint16_t num_antenna_ports,
const OranNumerology &numerology,
const OranTxWindows &tx_windows,
std::vector<OranCPlaneMsgInfo> &msg_infos,
)#

Convert FAPI UL_TTI.request to C-plane message infos

Processes a complete UL_TTI.request message and converts all contained PDUs (PUSCH, PUCCH, PRACH, SRS) to their corresponding C-plane messages. The output vector is cleared before processing. Caller should pre-allocate the vector with reserve() for best performance.

The FAPI slot field represents the slot within the frame. The conversion to ORAN subframe/slot depends on the numerology (SCS):

  • 15 kHz (μ=0): 1 slot per subframe

  • 30 kHz (μ=1): 2 slots per subframe

  • 60 kHz (μ=2): 4 slots per subframe

  • 120 kHz (μ=3): 8 slots per subframe

Parameters:
  • request[in] FAPI UL_TTI.request structure

  • body_len[in] Length of message body (from FAPI body_hdr.length or equivalent)

  • num_antenna_ports[in] Number of antenna ports in system

  • numerology[in] ORAN numerology parameters

  • tx_windows[in] Base transmission timing windows (for first symbol)

  • msg_infos[out] Output vector of C-plane message structures (cleared before use)

Return values:
  • OranErrc::Success – Operation completed successfully

  • OranErrc::invalid_num_antenna_ports – Number of antenna ports is zero

  • OranErrc::InvalidPrbAllocationRbSizeZero – PRB allocation has zero rb_size

  • OranErrc::invalid_prb_allocation_num_symbols_zero – PRB allocation has zero num_of_symbols

  • OranErrc::invalid_prb_allocation_exceeds_slot – Symbol allocation exceeds slot boundary

  • OranErrc::too_many_sections_for_symbol – Section limit exceeded for a start symbol

  • OranErrc::PduPayloadOutOfBounds – PDU parsing exceeded payload bounds

Returns:

Error code indicating success or specific error condition

std::error_code ran::oran::convert_ul_tti_request_to_cplane(
const scf_fapi_ul_tti_req_t &request,
std::size_t body_len,
std::uint16_t num_antenna_ports,
const OranNumerology &numerology,
const OranTxWindows &tx_windows,
PrbChunks &prb_chunks,
std::vector<OranCPlaneMsgInfo> &msg_infos,
)#

Convert FAPI UL_TTI.request to C-plane message infos (with pre-allocated buffer)

Overload for real-time performance-critical operations where the caller pre-allocates and reuses the PRB chunks buffer to avoid runtime allocations.

Parameters:
  • request[in] FAPI UL_TTI.request structure

  • body_len[in] Length of message body (from FAPI body_hdr.length or equivalent)

  • num_antenna_ports[in] Number of antenna ports in system

  • numerology[in] ORAN numerology parameters

  • tx_windows[in] Base transmission timing windows (for first symbol)

  • prb_chunks[inout] Pre-allocated PRB chunks buffer (cleared before use)

  • msg_infos[out] Output vector of C-plane message structures (cleared before use)

Return values:
  • OranErrc::Success – Operation completed successfully

  • OranErrc::invalid_num_antenna_ports – Number of antenna ports is zero

  • OranErrc::InvalidPrbAllocationRbSizeZero – PRB allocation has zero rb_size

  • OranErrc::invalid_prb_allocation_num_symbols_zero – PRB allocation has zero num_of_symbols

  • OranErrc::invalid_prb_allocation_exceeds_slot – Symbol allocation exceeds slot boundary

  • OranErrc::too_many_sections_for_symbol – Section limit exceeded for a start symbol

  • OranErrc::PduPayloadOutOfBounds – PDU parsing exceeded payload bounds

Returns:

Error code indicating success or specific error condition

constexpr std::uint32_t ran::oran::to_khz(
const SubcarrierSpacing scs,
) noexcept#

Convert SubcarrierSpacing enum to kHz value

Parameters:

scs[in] Subcarrier spacing enum

Returns:

SCS value in kHz

constexpr std::optional<SubcarrierSpacing> ran::oran::from_khz(
const std::uint32_t khz,
) noexcept#

Convert kHz value to SubcarrierSpacing enum

Parameters:

khz[in] SCS value in kHz (15, 30, 60, or 120)

Returns:

SubcarrierSpacing enum or nullopt if invalid

OranNumerology ran::oran::from_scs(SubcarrierSpacing scs)#

Create numerology from SubcarrierSpacing enum

Calculates all timing parameters based on 3GPP specifications:

  • Slots per subframe = SCS / 15 kHz

  • Slot period = 1ms / slots_per_subframe

  • Symbol duration = slot_period / 14 symbols

Parameters:

scs[in] Subcarrier spacing enum

Returns:

Calculated numerology parameters

OranNumerology ran::oran::from_scs_khz(std::uint32_t scs_khz)#

Create numerology from subcarrier spacing in kHz

Parameters:

scs_khz[in] Subcarrier spacing in kHz (15, 30, 60, or 120)

Throws:

std::invalid_argument – if SCS is not valid

Returns:

Calculated numerology parameters

OranSlotTiming ran::oran::fapi_to_oran_slot_timing(
const ran::fapi::FapiSlotTiming &fapi_timing,
) noexcept#

Convert FAPI slot timing to ORAN slot timing

Performs conversion from absolute slot number and slots-per-subframe to frame, subframe, and slot IDs. Handles uint8_t wrapping at frame 256 and FAPI SFN wrapping at 1024.

Parameters:

fapi_timing[in] FAPI slot timing containing absolute_slot and slots_per_subframe

Returns:

ORAN slot timing with frame, subframe, and slot IDs

inline const OranErrorCategory &ran::oran::oran_category() noexcept#

Get the singleton instance of the ORAN error category

Returns:

Reference to the ORAN error category

inline std::error_code ran::oran::make_error_code(
const OranErrc errc,
) noexcept#

Create an error_code from an OranErrc value

Parameters:

errc[in] The ORAN error code

Returns:

A std::error_code representing the ORAN error

constexpr bool ran::oran::is_success(const OranErrc errc) noexcept#

Check if an OranErrc represents success

Parameters:

errc[in] The error code to check

Returns:

true if the error code represents success, false otherwise

inline bool ran::oran::is_oran_success(
const std::error_code &errc,
) noexcept#

Check if an error_code represents ORAN success

An error code represents success if it evaluates to false (i.e., value is 0). This works regardless of the category (system, task, etc.).

Parameters:

errc[in] The error code to check

Returns:

true if the error code represents success, false otherwise

inline const char *ran::oran::get_error_name(
const OranErrc errc,
) noexcept#

Get the name of an OranErrc enum value

Parameters:

errc[in] The error code

Returns:

The enum name as a string

inline const char *ran::oran::get_error_name(
const std::error_code &ec,
) noexcept#

Get the name of an OranErrc from a std::error_code

Parameters:

ec[in] The error code

Returns:

The enum name as a string, or “unknown” if not an ORAN error

ran::oran::DECLARE_LOG_COMPONENT(
Oran,
OranGeneral,
OranCplane,
OranUplane,
OranBuffer,
OranFapi,
)#

Declare logging components for ORAN subsystem

union CPlaneSectionCommonHdr#
#include <cplane_types.hpp>

C-plane section common header union

Public Members

oran_cmsg_sect0_common_hdr sect_0_common_hdr = {}#

Section type 0 common header.

oran_cmsg_sect1_common_hdr sect_1_common_hdr#

Section type 1 common header.

oran_cmsg_sect3_common_hdr sect_3_common_hdr#

Section type 3 common header.

oran_cmsg_sect5_common_hdr sect_5_common_hdr#

Section type 5 common header.

struct CPlaneSectionExt11BundlesInfo#
#include <cplane_types.hpp>

C-plane Section Extension Type 11 bundle information

Public Members

std::uint8_t *bfw_iq = {}#

Beamforming weight IQ data pointer.

struct CPlaneSectionExt11Info#
#include <cplane_types.hpp>

C-plane Section Extension Type 11 information

Public Members

oran_cmsg_sect_ext_type_11 ext_hdr = {}#

Extension type 11 header.

oran_cmsg_sect_ext_type_11_disableBFWs_0_bfwCompHdr ext_comp_hdr = {}#

Beamforming compression header.

CPlaneSectionExt11BundlesInfo *bundles = {}#

Array of bundle information.

std::uint16_t num_prb_bundles = {}#

Number of PRB bundles.

std::uint16_t num_bund_prb = {}#

Number of PRBs per bundle.

std::uint8_t bundle_hdr_size = {}#

Bundle header size in bytes.

std::uint16_t bfw_iq_size = {}#

Beamforming weight IQ data size.

std::uint8_t bundle_size = {}#

Total bundle size in bytes.

bool static_bfw = {}#

Static beamforming weights flag.

std::uint8_t *bfw_iq = {}#

Beamforming weight IQ buffer with offset for this eAxC.

std::uint8_t start_bundle_offset_in_bfw_buffer = {}#

Start bundle offset due to PRB fragmentation.

struct CPlaneSectionExt4Info#
#include <cplane_types.hpp>

C-plane Section Extension Type 4 Info

Public Members

oran_cmsg_sect_ext_type_4 ext_hdr = {}#

Extension type 4 header.

struct CPlaneSectionExt5Info#
#include <cplane_types.hpp>

C-plane Section Extension Type 5 Info

Public Members

oran_cmsg_sect_ext_type_5 ext_hdr = {}#

Extension type 5 header.

struct CPlaneSectionExtInfo#
#include <cplane_types.hpp>

C-plane Section Extension Info

Public Members

oran_cmsg_ext_hdr sect_ext_common_hdr = {}#

Section extension common header

class MBuf : public ran::oran::OranBuf#
#include <dpdk_buf.hpp>

DPDK mbuf buffer implementation

Wraps an rte_mbuf to provide the OranBuf interface. This allows DPDK mbufs to be used with ORAN packet preparation functions.

Public Functions

explicit MBuf(rte_mbuf *mbuf)#

Construct buffer wrapping an rte_mbuf

Parameters:

mbuf[in] DPDK mbuf pointer

virtual std::uint8_t *data() override#

Get buffer data pointer

Returns:

Pointer to buffer data

virtual const std::uint8_t *data() const override#

Get buffer data pointer (const)

Returns:

Const pointer to buffer data

virtual std::size_t capacity() const override#

Get buffer capacity

Returns:

Maximum buffer size in bytes

virtual std::size_t size() const override#

Get current data size

Returns:

Current data size in bytes

virtual void set_size(std::size_t new_size) override#

Set buffer size

Parameters:

new_size[in] New buffer size in bytes

Throws:
  • std::length_error – if new_size exceeds buffer capacity

  • std::length_error – if new_size exceeds maximum mbuf data length (65535 bytes)

virtual void set_timestamp(std::uint64_t timestamp) override#

Set timestamp value (for DPDK mbuf compatibility)

This automatically sets the timestamp flag when needed.

Parameters:

timestamp[in] Timestamp value

virtual void clear_flags() override#

Clear all buffer flags (for DPDK mbuf compatibility)

inline rte_mbuf *get_mbuf() const#

Get underlying mbuf pointer

Returns:

DPDK mbuf pointer

inline std::uint8_t &at(const std::size_t index)#

Access element with bounds checking

Parameters:

index[in] Element index

Throws:

std::out_of_range – if index >= size()

Returns:

Reference to element at specified index

inline const std::uint8_t &at(const std::size_t index) const#

Access element with bounds checking (const version)

Parameters:

index[in] Element index

Throws:

std::out_of_range – if index >= size()

Returns:

Const reference to element at specified index

class OranBuf#
#include <oran_buf.hpp>

Abstract buffer interface for packet data

Subclassed by ran::oran::MBuf, ran::oran::VecBuf

Public Functions

OranBuf() = default#
virtual ~OranBuf() = default#
OranBuf(const OranBuf&) = default#

Copy constructor.

OranBuf &operator=(const OranBuf&) = default#

Copy assignment operator.

Returns:

Reference to this object

OranBuf(OranBuf&&) = default#

Move constructor.

OranBuf &operator=(OranBuf&&) = default#

Move assignment operator.

Returns:

Reference to this object

virtual std::uint8_t *data() = 0#

Get buffer data pointer

Returns:

Pointer to buffer data

virtual const std::uint8_t *data() const = 0#

Get buffer data pointer (const)

Returns:

Const pointer to buffer data

virtual std::size_t capacity() const = 0#

Get buffer capacity

Returns:

Maximum buffer size in bytes

virtual std::size_t size() const = 0#

Get current data size

Returns:

Current data size in bytes

virtual void set_size(std::size_t new_size) = 0#

Set data size

Parameters:

new_size[in] New data size in bytes

inline virtual void set_timestamp(std::uint64_t timestamp)#

Set timestamp value (for DPDK mbuf compatibility)

This automatically sets the timestamp flag when needed.

Parameters:

timestamp[in] Timestamp value

inline virtual void clear_flags()#

Clear all buffer flags (for DPDK mbuf compatibility)

template<typename T>
inline T *data_as()#

Template method for typed access to buffer data

Template Parameters:

T – Type to cast buffer data to

Returns:

Pointer to buffer data cast as type T

template<typename T>
inline T *data_at_offset(std::size_t offset)#

Template method for typed access at offset

Template Parameters:

T – Type to cast buffer data to

Parameters:

offset[in] Byte offset into buffer

Returns:

Pointer to buffer data at offset cast as type T

struct OranCPlaneMsgInfo#
#include <cplane_types.hpp>

Minimal C-plane message info structure

Public Members

CPlaneSectionCommonHdr section_common_hdr = {}#

Radio app header.

oran_pkt_dir data_direction = {}#

UL/DL direction.

bool has_section_ext = {}#

Has section extensions.

std::uint16_t ap_idx = {}#

Antenna port index.

std::array<OranCPlaneSectionInfo, MAX_CPLANE_SECTIONS> sections = {}#

Section data array.

std::uint8_t num_sections = {}#

Number of sections used.

std::uint64_t tx_window_start = {}#

Transmission window start timestamp.

std::uint64_t tx_window_bfw_start = {}#

Beamforming window start timestamp.

std::uint64_t tx_window_end = {}#

Transmission window end timestamp.

struct OranCPlaneSectionInfo#
#include <cplane_types.hpp>

Cleaned up C-plane section info without pointers

Public Members

bool csirs_of_multiplex_pdsch_csirs = {}#

CSI-RS multiplexed with PDSCH flag.

std::optional<CPlaneSectionExtInfo> ext4#

Optional section extensions (at most one of each type per section)

Extension type 4

std::optional<CPlaneSectionExtInfo> ext5#

Extension type 5.

std::optional<CPlaneSectionExtInfo> ext11#

Extension type 11 (has flexible arrays, use pointer)

class OranErrorCategory : public std::error_category#
#include <oran_errors.hpp>

Custom error category for ORAN errors

This class provides human-readable error messages and integrates ORAN errors with the standard C++ error handling system.

Public Functions

inline const char *name() const noexcept override#

Get the name of this error category

Returns:

The category name as a C-style string

inline std::string message(const int condition) const override#

Get a descriptive message for the given error code

Parameters:

condition[in] The error code value

Returns:

A descriptive error message

inline std::error_condition default_error_condition(
const int condition,
) const noexcept override#

Map ORAN errors to standard error conditions where applicable

Parameters:

condition[in] The error code value

Returns:

The equivalent standard error condition, or a default-constructed condition

Public Static Functions

static inline const char *name(const int condition)#

Get the name of the error code enum value

Parameters:

condition[in] The error code value

Returns:

The enum name as a string

class OranFlow#
#include <cplane_types.hpp>

Abstract flow interface for packet template and sequence generation

Subclassed by ran::oran::SimpleOranFlow

Public Functions

OranFlow() = default#
virtual ~OranFlow() = default#
OranFlow(const OranFlow&) = default#

Copy constructor.

OranFlow &operator=(const OranFlow&) = default#

Copy assignment operator.

Returns:

Reference to this object

OranFlow(OranFlow&&) = default#

Move constructor.

OranFlow &operator=(OranFlow&&) = default#

Move assignment operator.

Returns:

Reference to this object

virtual const PacketHeaderTemplate &get_packet_header_template(
) const = 0#

Get packet header template for this flow

Returns:

Reference to packet header template

virtual std::uint8_t next_sequence_id_uplink() = 0#

Generate next uplink sequence ID

Returns:

Next sequence ID for uplink packets

virtual std::uint8_t next_sequence_id_downlink() = 0#

Generate next downlink sequence ID

Returns:

Next sequence ID for downlink packets

struct OranNumerology#
#include <numerology.hpp>

ORAN numerology parameters derived from subcarrier spacing

All timing parameters calculated from SCS according to 3GPP TS 38.211. This struct encapsulates the relationship between subcarrier spacing and derived timing values (slot period, symbol duration, etc.).

Public Functions

OranSlotTiming calculate_slot_timing(
std::uint64_t absolute_slot,
) const#

Calculate slot timing from absolute slot number

Converts an absolute slot number (since SFN 0 slot 0) into frame, subframe, and slot indices.

Parameters:

absolute_slot[in] Absolute slot number since SFN 0 slot 0

Returns:

Slot timing information (frame, subframe, slot)

std::uint64_t calculate_slot_timestamp(
const OranSlotTiming &timing,
) const#

Calculate timestamp for a given slot

Converts frame, subframe, and slot indices into an absolute timestamp (relative to SFN 0 slot 0).

Parameters:

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

Returns:

Timestamp in nanoseconds since SFN 0 slot 0

Public Members

SubcarrierSpacing subcarrier_spacing = {}#

SCS enum value.

std::uint32_t slots_per_subframe = {}#

Slots per 1ms subframe.

std::uint64_t slot_period_ns = {}#

Slot period in nanoseconds.

std::uint64_t symbol_duration_ns = {}#

OFDM symbol duration in ns.

class OranPeer#
#include <cplane_types.hpp>

Abstract peer interface for timestamp tracking

Subclassed by ran::oran::SimpleOranPeer

Public Functions

OranPeer() = default#
virtual ~OranPeer() = default#
OranPeer(const OranPeer&) = default#

Copy constructor.

OranPeer &operator=(const OranPeer&) = default#

Copy assignment operator.

Returns:

Reference to this object

OranPeer(OranPeer&&) = default#

Move constructor.

OranPeer &operator=(OranPeer&&) = default#

Move assignment operator.

Returns:

Reference to this object

virtual std::uint64_t &get_last_dl_timestamp() = 0#

Get reference to last downlink timestamp

Returns:

Reference to last DL timestamp for modification

virtual std::uint64_t &get_last_ul_timestamp() = 0#

Get reference to last uplink timestamp

Returns:

Reference to last UL timestamp for modification

struct OranSlotTiming#
#include <cplane_types.hpp>

Slot timing information

Public Members

std::uint8_t frame_id = {}#

Frame ID (0-255)

std::uint8_t subframe_id = {}#

Subframe ID (0-9)

std::uint8_t slot_id = {}#

Slot ID (depends on numerology)

struct OranTxWindows#
#include <cplane_types.hpp>

Transmission timing windows

Public Members

std::uint64_t tx_window_start = {}#

Transmission window start timestamp (ns)

std::uint64_t tx_window_bfw_start = {}#

Beamforming window start timestamp (ns)

std::uint64_t tx_window_end = {}#

Transmission window end timestamp (ns)

struct PacketHeaderTemplate#
#include <cplane_types.hpp>

Packet header template for Ethernet + VLAN + eCPRI headers

Public Members

oran_ether_hdr eth#

Ethernet header.

oran_vlan_hdr vlan#

VLAN header.

oran_ecpri_hdr ecpri#

eCPRI header

struct PrbChunk#
#include <fapi_to_cplane.hpp>

PRB chunk representing a contiguous allocation in frequency and time

Public Members

std::uint16_t rb_start = {}#

Starting resource block index.

std::uint16_t rb_size = {}#

Number of resource blocks.

std::uint8_t start_symbol_index = {}#

Starting OFDM symbol index.

std::uint8_t num_of_symbols = {}#

Number of OFDM symbols.

struct PrbChunks#
#include <fapi_to_cplane.hpp>

Container for aggregated PRB chunks with pre-allocated capacity

Public Functions

inline PrbChunks()#
inline void clear()#

Clear all chunks

Public Members

std::vector<PrbChunk> chunks#

Vector of PRB chunks.

class SimpleOranFlow : public ran::oran::OranFlow#
#include <cplane_types.hpp>

Simple implementation of OranFlow interface

Public Functions

inline explicit SimpleOranFlow(
const PacketHeaderTemplate &template_hdr,
)#

Construct flow with packet header template

Parameters:

template_hdr[in] Packet header template to use

inline virtual const PacketHeaderTemplate &get_packet_header_template(
) const override#

Get packet header template for this flow

Returns:

Reference to packet header template

inline virtual std::uint8_t next_sequence_id_uplink() override#

Generate next uplink sequence ID

Returns:

Next sequence ID for uplink packets

inline virtual std::uint8_t next_sequence_id_downlink() override#

Generate next downlink sequence ID

Returns:

Next sequence ID for downlink packets

class SimpleOranPeer : public ran::oran::OranPeer#
#include <cplane_types.hpp>

Simple implementation of OranPeer interface

Public Functions

inline virtual std::uint64_t &get_last_dl_timestamp() override#

Get reference to last downlink timestamp

Returns:

Reference to last DL timestamp for modification

inline virtual std::uint64_t &get_last_ul_timestamp() override#

Get reference to last uplink timestamp

Returns:

Reference to last UL timestamp for modification

class VecBuf : public ran::oran::OranBuf#
#include <vec_buf.hpp>

Simple memory buffer implementation using std::vector

Public Functions

inline explicit VecBuf(std::size_t capacity)#

Construct buffer with specified capacity

Parameters:

capacity[in] Buffer capacity in bytes

inline virtual std::uint8_t *data() override#

Get buffer data pointer

Returns:

Pointer to buffer data

inline virtual const std::uint8_t *data() const override#

Get buffer data pointer (const)

Returns:

Const pointer to buffer data

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

Get buffer capacity

Returns:

Maximum buffer size in bytes

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

Get current data size

Returns:

Current data size in bytes

inline virtual void set_size(std::size_t new_size) override#

Set data size

Parameters:

new_size[in] New data size in bytes

inline virtual void set_timestamp(
const std::uint64_t timestamp,
) override#

Set timestamp value (for DPDK mbuf compatibility)

This automatically sets the timestamp flag when needed.

Parameters:

timestamp[in] Timestamp value

inline virtual void clear_flags() override#

Clear all buffer flags (for DPDK mbuf compatibility)

inline bool has_timestamp() const#

Get timestamp flag (for testing)

Returns:

True if timestamp flag is set

inline std::uint64_t get_timestamp() const#

Get timestamp value (for testing)

Returns:

Timestamp value