DAQIRI · NVIDIA

API Guide

Complete C++ API reference for DAQIRI. Include the canonical public header, daqiri/daqiri.h. All symbols live in the daqiri:: namespace.

C++17 CUDA ≥ 12.0 ConnectX-6 Dx+ Linux 5.4+ Apache 2.0
Key Concepts

BurstParams

All packet data flows through the BurstParams structure. A burst is a batch of packets grouped together for efficient DMA transfer between the NIC and the application. BurstParams carries pointers to packet buffers (CPU or GPU), packet count, port/queue IDs, segment count, byte totals, and per-packet lengths and flow IDs. Interact with it only through the helper functions — the internal layout is opaque.

Zero-Copy Design

Only pointers are passed between the NIC, DAQIRI internals, and your application. When you receive packets, you are reading the same buffers the NIC DMA'd into — no copies. This means you must explicitly free buffers when done. Failure to free will exhaust the memory pool, causing the NIC to drop packets and DAQIRI to return NO_FREE_BURST_BUFFERS or NO_FREE_PACKET_BUFFERS.

Segments

A segment is a contiguous memory region (CPU or GPU) holding part of a packet. The most common case is header-data split (HDS): segment 0 = headers (CPU), segment 1 = payload (GPU). CPU-only and batched-GPU modes use a single segment (segment 0).


Initialization
daqiri_initfunction

Initializes DAQIRI from a YAML config file or a NetworkConfig struct. After SUCCESS returns, all memory regions are allocated, NIC queues are configured, and worker threads are running.

// From YAML file Status daqiri::daqiri_init(const std::string& config_path); // From struct built in code Status daqiri::daqiri_init(const NetworkConfig& config);
#include <daqiri/daqiri.h>

auto status = daqiri::daqiri_init("path/to/config.yaml");
if (status != daqiri::Status::SUCCESS) {
    // handle init failure
}
💡

See the configuration reference for the full YAML schema and worked examples for DPDK and RDMA backends.

shutdownfunction

Stops all worker threads, drains queues, and releases all memory regions and NIC resources. Call once at the end of your application.

void daqiri::shutdown();

Receive (RX)

The three-step RX workflow: get a burst → access packet data → free buffers.

fn get_rx_burst (&burst, port_id, queue_id?) → Status

Non-blocking. Returns SUCCESS when a complete batch is available, or NULL_PTR when no burst is ready yet. Three overloads:

// From a specific port + queue
daqiri::get_rx_burst(&burst, port_id, queue_id);

// From any queue on a port (round-robin)
daqiri::get_rx_burst(&burst, port_id);

// From any queue on any port (round-robin)
daqiri::get_rx_burst(&burst);
fn get_num_packets (burst) → int

Returns the number of packets in the burst. Always call this before iterating — do not assume batch_size.

fn get_packet_ptr (burst, pkt_idx) → void*

Returns a pointer to the packet buffer for packet pkt_idx. For CPU-only or batched GPU (single-segment) configurations, this is the full packet. For HDS, use get_segment_packet_ptr() instead.

for (int i = 0; i < daqiri::get_num_packets(burst); i++) {
    void*    pkt  = daqiri::get_packet_ptr(burst, i);
    uint32_t len  = daqiri::get_packet_length(burst, i);
    uint16_t flow = daqiri::get_packet_flow_id(burst, i);
    // process...
}
fn get_segment_packet_ptr (burst, seg_idx, pkt_idx) → void*

Returns a pointer to segment seg_idx of packet pkt_idx. Use for header-data split (HDS) configurations: segment 0 is a CPU pointer to the packet headers; segment 1 is a GPU device pointer to the payload.

// Header-data split: two segments per packet
for (int i = 0; i < daqiri::get_num_packets(burst); i++) {
    void* hdr = daqiri::get_segment_packet_ptr(burst, 0, i); // CPU
    void* pay = daqiri::get_segment_packet_ptr(burst, 1, i); // GPU
    uint32_t hlen = daqiri::get_segment_packet_length(burst, 0, i);
    uint32_t plen = daqiri::get_segment_packet_length(burst, 1, i);
    // pay is already on GPU — pass directly to CUDA kernel
}
fn Free Buffer Functions

Buffers must be freed when done or the memory pool will be exhausted. Several options depending on how your pipeline releases buffers:

// Most common: free all packets + burst metadata
daqiri::free_all_packets_and_burst_rx(burst);

// Free a single packet (all segments)
daqiri::free_packet(burst, pkt_idx);

// Free one segment of one packet
daqiri::free_packet_segment(burst, seg_idx, pkt_idx);

// Free all packets for one segment, then the burst metadata
daqiri::free_all_segment_packets(burst, seg_idx);
daqiri::free_rx_burst(burst);
⚠️

Forgetting to free buffers is the most common cause of dropped packets. If you see NO_FREE_BURST_BUFFERS or NO_FREE_PACKET_BUFFERS, check your free path first.


Transmit (TX)

The three-step TX workflow: allocate a burst → fill packets → send.

fn create_tx_burst_params () → BurstParams*

Allocates a new TX BurstParams object. Follow with set_header() to configure port, queue, batch size, and segment count, then call get_tx_packet_burst() to acquire buffer space.

auto burst = daqiri::create_tx_burst_params();
daqiri::set_header(burst, port_id, queue_id,
                    batch_size, num_segments);

// Optionally check availability first
if (daqiri::is_tx_burst_available(burst))
    daqiri::get_tx_packet_burst(burst);
fn set_eth/ipv4/udp_header + set_udp_payload (...)

Helper functions to fill standard Ethernet/IP/UDP headers and payload for each packet in the burst. Or write raw packet data directly via get_packet_ptr().

for (int i = 0; i < batch_size; i++) {
    daqiri::set_eth_header(burst, i, dst_mac);
    daqiri::set_ipv4_header(burst, i, ip_payload_len,
                              IPPROTO_UDP, src_ip, dst_ip);
    daqiri::set_udp_header(burst, i, udp_payload_len,
                              src_port, dst_port);
    daqiri::set_udp_payload(burst, i, payload_ptr, payload_size);
    daqiri::set_packet_lengths(burst, i, {total_pkt_len});
}
fn send_tx_burst (burst) → void

Enqueues the burst to the TX worker thread, which sends it to the NIC via DMA. Returns immediately — the worker thread handles actual transmission asynchronously.

daqiri::send_tx_burst(burst);
fn set_packet_tx_time (burst, pkt_idx, ptp_timestamp) → void

Schedules a packet for hardware-timed transmission at the given PTP timestamp. Requires accurate_send: true in the TX config and ConnectX-7 or later hardware.

daqiri::set_packet_tx_time(burst, pkt_idx, ptp_timestamp);
ℹ️

Enable accurate send in YAML: tx.accurate_send: true. Not supported on ConnectX-6 Dx.


Utility Functions
// Get MAC address of a NIC port
char mac[6];
daqiri::get_mac_addr(port_id, mac);

// Look up port ID by interface name or PCIe address
int port = daqiri::get_port_id("rx_port");

// Traffic control
daqiri::drop_all_traffic(port_id);   // drop all incoming packets
daqiri::allow_all_traffic(port_id);  // restore normal reception

// Drain stale packets from a queue
daqiri::flush_port_queue(port_id, queue_id);

// Print NIC statistics to stdout
daqiri::print_stats();

// Graceful shutdown
daqiri::shutdown();

Status Codesenum

All DAQIRI functions that can fail return daqiri::Status. Always check the return value in production code.

StatusMeaning
SUCCESSOperation completed successfully.
NULL_PTRBurst or internal pointer not initialized, or no data is ready yet (normal on empty RX poll).
NO_FREE_BURST_BUFFERSMetadata buffer pool exhausted. Increase tx/rx_meta_buffers in config, or free bursts faster.
NO_FREE_PACKET_BUFFERSPacket buffer pool exhausted. Free buffers faster or increase num_bufs in memory region config.
NOT_READYSystem not yet initialized — daqiri_init() has not been called or has not returned SUCCESS.
INVALID_PARAMETERAn invalid argument was passed (e.g., out-of-range port or queue ID).
NO_SPACE_AVAILABLEInternal ring or queue is full. Back off and retry.
NOT_SUPPORTEDOperation is not supported by the current backend (e.g., timed TX on DPDK without ConnectX-7).
GENERIC_FAILUREUnspecified failure. Check logs for more detail.
CONNECT_FAILURERDMA connection failed — verify IP addresses, port, and network reachability.
INTERNAL_ERRORAn internal error occurred in the backend. File an issue on GitHub with logs.
← Back to Home
Getting Started Configuration daqiri.h ↗