Net#

Overview#

The Net library provides a high-performance network communication framework built on top of DPDK and DOCA. It supports CPU-based packet processing with DPDK and GPU-accelerated networking with DOCA GPUNetIO, which enables GPU-direct zero-copy packet processing.

Key Features#

  • DPDK Integration: Efficient packet processing using DPDK for CPU-based operations

  • DOCA GPUNetIO: GPU-direct networking with kernel-initiated operations

  • RDMA Support: Remote Direct Memory Access for high-bandwidth, low-latency transfers

  • GPUDirect RDMA: Direct data transfers between NIC and GPU memory without CPU staging

  • Queue Management: Flexible TX/RX queue configuration for both DPDK and DOCA

  • Memory Pool Management: Efficient buffer management with host-pinned memory support

GPU-Accelerated Networking#

The Net library uses DOCA GPUNetIO for direct packet transfer between NIC and GPU memory, and GDRCopy for efficient CPU access to GPU memory when needed for control operations.

DOCA GPUNetIO#

DOCA GPUNetIO enables real-time GPU processing for network packets by removing the CPU from the critical path. Instead of requiring CPU coordination for packet reception via GPUDirect RDMA and kernel notification, DOCA GPUNetIO allows CUDA kernels to control Ethernet and RDMA communications directly, sending and receiving packets with precise timing control.

GDRCopy#

GDRCopy is a low-latency GPU memory copy library based on NVIDIA GPUDirect RDMA technology. It allows the CPU to directly access GPU memory.

GDRCopy provides low-latency CPU access to GPU memory without kernel driver overhead, avoiding the costs of standard cudaMemcpy operations. The Net library uses it for:

  • Allocating GPU memory buffers accessible from CPU

  • CPU initializing GPU queue structures before launching kernels

  • CPU reading packet counters and status from GPU memory

  • CPU-GPU synchronization primitives

This enables efficient control plane operations while keeping data plane operations GPU-centric for maximum performance.

Quick Start#

1. Include Required Headers#

#include "net/dpdk_types.hpp"
#include "net/env.hpp"
#include "net/nic.hpp"

2. Configure the Environment#

Create configuration for DPDK, NIC, and queues:

EnvConfig config{};
config.gpu_device_id = GpuDeviceId{0};            // Use first GPU
config.nic_config.nic_pcie_addr = "0000:3a:00.0"; // NIC PCIe address

// Configure DPDK
config.dpdk_config.app_name = "my_app";
config.dpdk_config.file_prefix = "my_prefix";
config.dpdk_config.dpdk_core_id = 0;

3. Configure DOCA TX Queue#

Configure DOCA TX queue for GPU-accelerated sending:

DocaTxQConfig tx_config{};
tx_config.nic_pcie_addr = "0000:3a:00.0";
tx_config.dest_mac_addr = MacAddress::from_string("aa:bb:cc:dd:ee:ff").value();
tx_config.pkt_size = 1024;
tx_config.pkt_num = 64;
tx_config.max_sq_descr_num = 8192;
tx_config.ether_type = 0x88b5;

4. Configure DOCA RX Queue#

Configure DOCA RX queue for GPU-accelerated receiving:

DocaRxQConfig rx_config{};
rx_config.nic_pcie_addr = "0000:3a:00.0";
rx_config.sender_mac_addr = MacAddress::from_string("aa:bb:cc:dd:ee:ff").value();
rx_config.max_pkt_num = 16384; // Maximum packets in queue
rx_config.max_pkt_size = 1024; // Maximum packet size
rx_config.ether_type = 0x88b5; // Filter by EtherType

5. Initialize and Use the Environment#

// Configure environment
EnvConfig config{};
config.gpu_device_id = GpuDeviceId{0};
config.nic_config.nic_pcie_addr = "0000:3a:00.0"; // Replace with your NIC address
config.dpdk_config.file_prefix = "my_app_prefix";

// Configure DOCA TX queue
DocaTxQConfig tx_config{};
tx_config.nic_pcie_addr = "0000:3a:00.0"; // Replace with your NIC address
tx_config.dest_mac_addr = MacAddress::from_string("00:11:22:33:44:55").value();
tx_config.pkt_size = 1024;
tx_config.pkt_num = 64;
tx_config.max_sq_descr_num = 8192;
tx_config.ether_type = 0x88b5;
config.nic_config.doca_txq_configs.push_back(tx_config);

// Configure DOCA RX queue
DocaRxQConfig rx_config{};
rx_config.nic_pcie_addr = "0000:3a:00.0"; // Replace with your NIC address
rx_config.sender_mac_addr = MacAddress::from_string("00:11:22:33:44:55").value();
rx_config.max_pkt_num = 16384;
rx_config.max_pkt_size = 1024;
rx_config.ether_type = 0x88b5;
config.nic_config.doca_rxq_configs.push_back(rx_config);

Environment Management#

The Env class provides RAII-based management of the entire networking environment.

Environment Initialization#

The environment performs these initialization steps:

  1. Validates CUDA device count and GPU device ID

  2. Validates NIC availability and configuration

  3. Initializes DPDK EAL (Environment Abstraction Layer)

  4. Creates and initializes GPU device

  5. Creates and initializes NIC with configured queues

Important

The environment can only be initialized once because DPDK EAL initialization can only be called one time per application. Create the Env object at application startup and reuse it throughout the application lifetime.

After configuration, initialize and use the environment:

// Initialize environment
const Env env{config};

// Check GPU availability
if (env.has_gpu()) {
    const auto &gpu = env.gpu();
    // Verify GPU is initialized
    if (!gpu.pci_bus_id().empty()) {
        // Use the GPU
    }
}

// Access NIC and queues
const auto &nic = env.nic();
const auto &pci_addr = nic.pci_address();
const auto &mac_addr = nic.mac_address();

// Get DOCA TX queue for GPU kernel usage
const auto *txq_params = nic.doca_tx_queue(0).params();

// Get DOCA RX queue for GPU kernel usage
const auto *rxq_params = nic.doca_rx_queue(0).params();

CPU-Only Mode#

For CPU-based packet processing without GPU acceleration:

EnvConfig config{};
config.nic_config.nic_pcie_addr = "0000:3a:00.0";
config.dpdk_config.file_prefix = "cpu_app";

// Configure DPDK TX queue instead of DOCA queue
DpdkTxQConfig dpdk_tx_config{};
dpdk_tx_config.txq_size = 128;
config.nic_config.dpdk_txq_configs.push_back(dpdk_tx_config);

// Configure mempool for buffer management
MempoolConfig mempool_config{};
mempool_config.name = "my_mempool";
mempool_config.num_mbufs = 1024;
mempool_config.mtu_size = 1514;
mempool_config.host_pinned = HostPinned::No;
config.nic_config.mempool_configs.push_back(mempool_config);

Discovering Available NICs#

// Discover all Mellanox NICs in the system
const auto nics = discover_mellanox_nics();

for (const auto &nic_addr : nics) {
    std::cout << "Found NIC: " << nic_addr << "\n";
}

// Use the first available NIC
if (!nics.empty()) {
    EnvConfig config{};
    config.nic_config.nic_pcie_addr = nics.front();
}

NIC Management#

The Nic class manages network interface cards with automatic resource cleanup.

NIC Information#

// Get NIC properties
const auto &nic_pci_addr = nic.pci_address();
const auto &nic_mac_addr = nic.mac_address();
const auto nic_port_id = nic.dpdk_port_id();

// Check RDMA support
if (const auto rdma_result = nic.is_rdma_supported(); rdma_result) {
    if (*rdma_result) {
        std::cout << "RDMA supported\n";
    }
}

Queue Access#

// Access DOCA TX queues
const auto &doca_tx_queues = nic.doca_tx_queues();
const auto &doca_tx_queue_0 = nic.doca_tx_queue(0);

// Access DOCA RX queues
const auto &doca_rx_queues = nic.doca_rx_queues();
const auto &doca_rx_queue_0 = nic.doca_rx_queue(0);

DOCA TX Queue Configuration#

DOCA TX queues enable GPU-direct packet transmission using DOCA GPUNetIO.

Basic TX Queue Setup#

DocaTxQConfig tx_config{};
tx_config.nic_pcie_addr = "0000:3a:00.0";
tx_config.dest_mac_addr = MacAddress::from_string("aa:bb:cc:dd:ee:ff").value();
tx_config.pkt_size = 1024;
tx_config.pkt_num = 64;
tx_config.max_sq_descr_num = 8192;
tx_config.ether_type = 0x88b5;

TX Queue with VLAN Tagging#

DocaTxQConfig tx_config{};
tx_config.nic_pcie_addr = "0000:3a:00.0";
tx_config.dest_mac_addr = MacAddress::from_string("aa:bb:cc:dd:ee:ff").value();
tx_config.pkt_size = 1024;
tx_config.pkt_num = 64;
tx_config.max_sq_descr_num = 8192;
tx_config.ether_type = 0x88b5;
tx_config.vlan_tci = 100; // VLAN ID 100 (inserts 802.1Q tag)

Using TX Queue in CUDA Kernel#

From the sender sample application, showing how to use DOCA TX queue in GPU kernels:

// Get DOCA TX queue parameters for GPU kernel
const auto *doca_txq = env.nic().doca_tx_queue(0).params();
if (doca_txq == nullptr) {
    RT_LOGC_ERROR(Net::NetDoca, "Failed to get DOCA TX queue structure");
    return EXIT_FAILURE;
}

// Launch GPU kernel with DOCA TX queue
const framework::utils::CudaStream stream;
const auto result = launch_gpunetio_sender_kernel(stream.get(), *doca_txq);
if (result != 0) {
    RT_LOGC_ERROR(Net::NetGpu, "Failed to launch sender kernel: {}", result);
    return EXIT_FAILURE;
}

DOCA RX Queue Configuration#

DOCA RX queues enable GPU-direct packet reception with hardware flow filtering using DOCA GPUNetIO.

Hardware Flow Filtering#

RX queues use hardware flow steering rules to filter incoming packets directly at the NIC level. The filtering is based on:

  • MAC Address (sender_mac_addr): Filters packets from a specific source MAC address

  • EtherType (ether_type): Filters packets with a specific Ethernet protocol type (e.g., 0x88b5 for custom protocols)

  • VLAN Tag (vlan_tci, optional): Filters packets with a specific VLAN ID when VLAN tagging is used

The NIC hardware performs the filtering before packets reach the GPU memory, eliminating unnecessary packet copies and processing.

Basic RX Queue Setup#

DocaRxQConfig rx_config{};
rx_config.nic_pcie_addr = "0000:3a:00.0";
rx_config.sender_mac_addr = MacAddress::from_string("aa:bb:cc:dd:ee:ff").value();
rx_config.max_pkt_num = 16384; // Maximum packets in queue
rx_config.max_pkt_size = 1024; // Maximum packet size
rx_config.ether_type = 0x88b5; // Filter by EtherType

RX Queue with VLAN Filtering#

DocaRxQConfig rx_config{};
rx_config.nic_pcie_addr = "0000:3a:00.0";
rx_config.sender_mac_addr = MacAddress::from_string("aa:bb:cc:dd:ee:ff").value();
rx_config.max_pkt_num = 16384;
rx_config.max_pkt_size = 1024;
rx_config.ether_type = 0x88b5;
rx_config.vlan_tci = 100; // Filter VLAN ID 100

Using RX Queue in CUDA Kernel#

From the receiver sample application, showing how to use DOCA RX queue in GPU kernels:

// Get DOCA RX queue parameters for GPU kernel
const auto *doca_rxq = env.nic().doca_rx_queue(0).params();
if (doca_rxq == nullptr) {
    RT_LOGC_ERROR(Net::NetDoca, "Failed to get DOCA RX queue structure");
    return EXIT_FAILURE;
}

auto gpu_exit_condition = make_unique_device<uint32_t>(1);
auto cpu_exit_condition = make_unique_pinned<uint32_t>(1);

*cpu_exit_condition = 0;
if (!cuda_memcpy_host_to_device(
            gpu_exit_condition.get(), cpu_exit_condition.get(), sizeof(uint32_t))) {
    return EXIT_FAILURE;
}

// Launch GPU kernel with DOCA RX queue
const framework::utils::CudaStream stream;
const auto result =
        launch_gpunetio_receiver_kernel(stream.get(), *doca_rxq, gpu_exit_condition.get());
if (result != 0) {
    RT_LOGC_ERROR(Net::NetGpu, "Failed to launch receiver kernel: {}", result);
    return EXIT_FAILURE;
}

DPDK Queue Configuration#

DPDK queues provide CPU-based packet processing without GPU acceleration.

DPDK TX Queue Setup#

DpdkTxQConfig dpdk_tx_config{};
dpdk_tx_config.txq_size = 128; // TX queue size

Sending Packets with DPDK#

From the sender sample application:

static constexpr std::string_view MESSAGE = "Hello DPDK";
static constexpr std::uint32_t MESSAGE_LEN = MESSAGE.size();

RT_LOGC_DEBUG(Net::NetDpdk, "Sending message via DPDK (CPU-only mode): '{}'", MESSAGE);

const auto &src_mac = env.nic().mac_address();
const EthernetHeader eth_header{src_mac, dest_mac, SAMPLE_ETHER_TYPE, SAMPLE_VLAN_ID};

// Create packet payload with length prefix
// Format: [4-byte length in big-endian][message content]
std::vector<std::uint8_t> payload(4 + MESSAGE_LEN);

// Write length in big-endian format
payload[0] = (MESSAGE_LEN >> 24U) & 0xFFU;
payload[1] = (MESSAGE_LEN >> 16U) & 0xFFU;
payload[2] = (MESSAGE_LEN >> 8U) & 0xFFU;
payload[3] = MESSAGE_LEN & 0xFFU;

// Write message content
const std::span<std::uint8_t> payload_content_span{payload.data() + 4, MESSAGE_LEN};
std::copy(MESSAGE.begin(), MESSAGE.end(), payload_content_span.begin());
const std::span<const std::uint8_t> payload_span{payload.data(), payload.size()};
const std::vector<std::span<const std::uint8_t>> messages = {payload_span};

return env.nic().send(0 /* dpdk_txq_id */, 0 /* mempool_id */, messages, eth_header);

Memory Pool Management#

Mempools manage packet buffer allocation for DPDK operations.

Mempool Configuration#

MempoolConfig mempool_config{};
mempool_config.name = "my_mempool";
mempool_config.num_mbufs = 1024; // Number of buffers
mempool_config.mtu_size = 1514;  // MTU size
mempool_config.host_pinned = HostPinned::No;

Host-Pinned Memory#

For improved performance with GPU operations, use host-pinned memory. When combined with GPU memory buffers, GDRCopy enables efficient direct CPU access to GPU memory:

MempoolConfig mempool_config{};
mempool_config.name = "pinned_mempool";
mempool_config.num_mbufs = 2048;
mempool_config.mtu_size = 9000;               // Jumbo frames
mempool_config.host_pinned = HostPinned::Yes; // Pin memory

Multiple Mempools#

// Small packet mempool
MempoolConfig small_pool{};
small_pool.name = "small_packets";
small_pool.num_mbufs = 1024;
small_pool.mtu_size = 1514;
small_pool.host_pinned = HostPinned::No;
config.nic_config.mempool_configs.push_back(small_pool);

// Large packet mempool
MempoolConfig large_pool{};
large_pool.name = "large_packets";
large_pool.num_mbufs = 512;
large_pool.mtu_size = 9000;
large_pool.host_pinned = HostPinned::Yes;
config.nic_config.mempool_configs.push_back(large_pool);

MAC Address Handling#

Type-Safe MAC Addresses#

// Parse MAC address from string
const auto mac = MacAddress::from_string("aa:bb:cc:dd:ee:ff");
if (mac) {
    std::cout << "Valid MAC: " << mac->to_string() << "\n";
}

// Check for zero MAC address
const MacAddress mac_addr{};
if (mac_addr.is_zero()) {
    std::cout << "MAC address is all zeros\n";
}

// Compare MAC addresses
const auto mac1 = MacAddress::from_string("aa:bb:cc:dd:ee:ff").value();
const auto mac2 = MacAddress::from_string("aa:bb:cc:dd:ee:ff").value();
if (mac1 == mac2) {
    std::cout << "MAC addresses match\n";
}

For more examples, see:

  • framework/net/samples/net_sender.cpp - GPU-accelerated packet sender

  • framework/net/samples/net_receiver.cpp - GPU-accelerated packet receiver

  • framework/net/samples/net_samples.cpp - Common utilities and DPDK examples

  • framework/net/tests/net_sample_tests.cpp - Documentation examples

  • framework/net/tests/net_env_tests.cpp - Environment configuration validation

External Resources#

API Reference#

Complete C++ API documentation for the Net framework.

enum class framework::net::DpdkPortState#

DPDK port configuration result states

Represents the possible outcomes when attempting to configure a DPDK ethernet port. Used by dpdk_try_configure_port to indicate whether the configuration operation succeeded, failed, or was unnecessary.

Values:

enumerator ConfigureSuccess#

Port configuration succeeded.

enumerator ConfigureError#

Port configuration failed.

enumerator AlreadyConfigured#

Port was already configured.

enum class framework::net::PcieMrrs : std::uint8_t#

PCIe Maximum Read Request Size values

Values:

enumerator Bytes128#

000b = 128 bytes

enumerator Bytes256#

001b = 256 bytes

enumerator Bytes512#

010b = 512 bytes

enumerator Bytes1024#

011b = 1024 bytes

enumerator Bytes2048#

100b = 2048 bytes

enumerator Bytes4096#

101b = 4096 bytes

enum class framework::net::HostPinned#

Host memory pinning configuration for DPDK mempool

Values:

enumerator No#

Host memory not pinned.

enumerator Yes#

Host memory pinned.

enum class framework::net::DpdkErrc : std::uint8_t#

DPDK error codes compatible with std::error_code

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

Values:

enumerator Success#

Operation succeeded.

enumerator EalInitFailed#

EAL initialization failed.

enumerator EalCleanupFailed#

EAL cleanup failed.

enumerator PortMtuFailed#

Failed to set port MTU.

enumerator VmTuneFailed#

Virtual memory tuning failed.

enumerator FlowIsolationFailed#

Flow rule isolation failed.

enumerator FlowControlGetFailed#

Failed to get flow control status.

enumerator FlowControlSetFailed#

Failed to set flow control.

enumerator DevStartFailed#

Failed to start ethernet device.

enumerator DevStopFailed#

Failed to stop ethernet device.

enumerator TxQueueSetupFailed#

TX queue setup failed.

enumerator TimestampFieldFailed#

Timestamp field registration failed.

enumerator TimestampFlagFailed#

Timestamp flag registration failed.

enumerator PcieReadFailed#

PCIe register read failed.

enumerator PcieWriteFailed#

PCIe register write failed.

enumerator PcieVerifyReadFailed#

PCIe verification read failed.

enumerator PcieVerifyMismatch#

PCIe verification value mismatch.

enumerator LinkInfoFailed#

Link info retrieval failed.

enumerator LinkDown#

Ethernet link is down.

enumerator StatsFailed#

Statistics retrieval failed.

enumerator DevInfoFailed#

Device info retrieval failed.

enumerator NoInterfaceIndex#

No interface index available.

enumerator UnsupportedDriver#

Non-Mellanox driver not supported.

enumerator InterfaceNameFailed#

Interface name retrieval failed.

enumerator MempoolCreateFailed#

Mempool creation failed.

enumerator MempoolDestroyFailed#

Mempool destruction failed.

enumerator MbufAllocFailed#

Mbuf allocation failed.

enumerator PacketSendFailed#

Packet transmission failed.

enumerator InvalidParameter#

Invalid parameter provided.

enum class framework::net::NetSample#

Network sample application type

Values:

enumerator Sender#

Network sender application.

enumerator Receiver#

Network receiver application.

using framework::net::DocaDevicePtr = std::unique_ptr<doca_dev, DocaDeviceDeleter>#

Type alias for DOCA device unique pointer.

static constexpr std::uint32_t framework::net::DEFAULT_MAX_RETRY_COUNT = 1000#

Default maximum retry count for DPDK operations.

void framework::net::doca_log_versions()#

Log DOCA SDK and runtime version information.

doca_error_t framework::net::doca_init_logging(
doca_log_backend **sdk_log,
)#

Initialize DOCA logging backends.

Parameters:

sdk_log[out] SDK log backend (optional, can be nullptr)

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

doca_error_t framework::net::doca_open_device_with_pci(
const std::string_view pci_addr,
doca_dev **retval,
)#

Open a DOCA device according to a given PCI address.

Parameters:
  • pci_addr[in] PCI address

  • retval[out] Pointer to doca_dev struct, nullptr if not found

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

doca_error_t framework::net::doca_open_and_probe_device(
std::string_view nic_pcie_addr,
doca_dev **ddev,
)#

Open and probe a DOCA network device.

Parameters:
  • nic_pcie_addr[in] Network card PCIe address

  • ddev[out] DOCA device

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

doca_error_t framework::net::doca_close_device(doca_dev *ddev)#

Close a DOCA device.

Parameters:

ddev[in] DOCA device to close

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

tl::expected<bool, std::string> framework::net::is_device_cx6(
doca_dev *ddev,
)#

Check if device is a CX-6 device.

Parameters:

ddev[in] DOCA device

Returns:

True if CX-6 device, error message on failure

doca_error_t framework::net::doca_open_cuda_device(
const std::string_view gpu_pcie_addr,
doca_gpu **gpu_dev,
)#

Open and initialize a DOCA GPU device.

Parameters:
  • gpu_pcie_addr[in] GPU PCIe address

  • gpu_dev[out] DOCA GPU device

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

doca_error_t framework::net::doca_close_cuda_device(
doca_gpu *gpu_dev,
)#

Close and destroy a DOCA GPU device.

Parameters:

gpu_dev[in] DOCA GPU device to destroy

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

std::string framework::net::doca_device_id_to_pci_bus_id(
int cuda_device_id,
)#

Convert CUDA device ID to PCI bus ID.

Parameters:

cuda_device_id[in] CUDA device ID

Returns:

PCI bus ID string (e.g., “0000:3b:00.0”)

doca_error_t framework::net::doca_get_dpdk_port_id(
doca_dev *dev_input,
uint16_t *port_id,
)#

Get DPDK port ID for a DOCA device.

Parameters:
  • dev_input[in] DOCA device

  • port_id[out] DPDK port ID

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

doca_error_t framework::net::doca_get_mac_addr_from_pci(
const std::string_view pci_addr,
MacAddress &mac_addr,
)#

Get MAC address from PCIe address.

Searches through all available DOCA devices to find the one with the specified PCIe address and retrieves its MAC address.

Parameters:
  • pci_addr[in] PCIe address string (e.g., “0000:3a:00.0”)

  • mac_addr[out] Buffer to store the 6-byte MAC address

Returns:

DOCA_SUCCESS on success

Returns:

DOCA_ERROR_INVALID_VALUE if parameters are nullptr

Returns:

DOCA_ERROR_NOT_FOUND if no device with specified PCIe address is found

Returns:

Other DOCA errors on device enumeration or MAC retrieval failures

doca_error_t framework::net::doca_create_rxq(
struct DocaRxQParams *rxq,
doca_gpu *gpu_dev,
doca_dev *ddev,
uint32_t max_pkt_num,
uint32_t max_pkt_size,
const std::optional<DocaSemItems> &sem_items,
)#

Create DOCA Ethernet RX queue for GPU.

Parameters:
  • rxq[in] DOCA Eth RX queue handler

  • gpu_dev[in] DOCA GPUNetIO device

  • ddev[in] DOCA device

  • max_pkt_num[in] Maximum number of packets in queue

  • max_pkt_size[in] Maximum packet size in bytes

  • sem_items[in] Semaphore configuration (if not set, no semaphore created)

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

doca_error_t framework::net::doca_destroy_rxq(
struct DocaRxQParams *rxq,
)#

Destroy DOCA Ethernet RX queue for GPU.

Parameters:

rxq[in] DOCA Eth RX queue handler

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

doca_error_t framework::net::doca_destroy_flow_rule(
struct DocaRxQParams *rxq,
)#

Cleanup DPDK flow rule to avoid reference issues during RX queue destruction.

Parameters:

rxq[in] DOCA Eth RX queue handler containing flow rule

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

doca_error_t framework::net::doca_create_flow_rule(
struct DocaRxQParams *rxq,
const std::string_view nic_pcie_addr,
const MacAddress &sender_mac_addr,
uint16_t ether_type,
const std::optional<uint16_t> &vlan_tci = std::nullopt,
)#

Set up DPDK flow rules to direct packets to GPU receive queue

Configures DPDK flow rules to match packets with specific source and destination MAC addresses and specified EtherType, directing them to the GPU receive queue. Optionally matches VLAN TCI when provided.

Parameters:
  • rxq[in] Receive queue structure with GPU queue info

  • nic_pcie_addr[in] NIC PCIe address for receiver MAC lookup

  • sender_mac_addr[in] Sender MAC address

  • ether_type[in] EtherType value to match in flow rule

  • vlan_tci[in] Optional VLAN TCI value (if not set, no VLAN matching)

Returns:

DOCA_SUCCESS on success

Returns:

DOCA_ERROR_BAD_STATE on DPDK configuration or flow rule failures

Returns:

DOCA_ERROR_NOT_FOUND if DPDK port ID cannot be found

Returns:

Other DOCA errors on MAC address retrieval failures

doca_error_t framework::net::doca_create_txq(
struct DocaTxQParams *txq,
doca_gpu *gpu_dev,
doca_dev *ddev,
uint32_t pkt_size,
uint32_t pkt_num,
uint32_t max_sq_descr_num,
const std::string_view nic_pcie_addr,
const MacAddress &dest_mac_addr,
uint16_t ether_type,
const std::optional<uint16_t> &vlan_tci = std::nullopt,
)#

Create DOCA Ethernet TX queue for GPU.

Parameters:
  • txq[in] DOCA Eth TX queue handler

  • gpu_dev[in] DOCA GPUNetIO device

  • ddev[in] DOCA device

  • pkt_size[in] Packet size to send

  • pkt_num[in] Number of packets

  • max_sq_descr_num[in] Maximum number of send queue descriptors

  • nic_pcie_addr[in] NIC PCIe address for source MAC lookup

  • dest_mac_addr[in] Destination MAC address string in format “XX:XX:XX:XX:XX:XX”

  • ether_type[in] EtherType value to use in packet headers

  • vlan_tci[in] Optional VLAN tag control information; when set, packets are tagged with the provided 802.1Q VLAN TCI

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

doca_error_t framework::net::doca_destroy_txq(
struct DocaTxQParams *txq,
)#

Destroy DOCA Ethernet TX queue for GPU.

Parameters:

txq[in] DOCA Eth TX queue handler

Returns:

DOCA_SUCCESS on success and DOCA_ERROR otherwise

bool framework::net::doca_is_gdrcopy_compatible_size(
size_t size,
) noexcept#

Check if size meets GDRCopy requirements.

Parameters:

size[in] Size to check

Returns:

true if size is GDRCopy compatible, false otherwise

size_t framework::net::doca_align_to_gpu_page(size_t size) noexcept#

Align size to GPU page boundary for GDRCopy compatibility.

Parameters:

size[in] Original size

Returns:

Size aligned to GPU page boundary

tl::expected<bool, std::string> framework::net::doca_is_rdma_supported(
doca_dev *ddev,
)#

Check if NIC device supports RDMA operations.

Verifies that the DOCA device can perform RDMA write operations, which is required for GPU-accelerated RDMA datapath.

Parameters:

ddev[in] DOCA device to check

Returns:

Pair of (error_code, is_supported) - first is DOCA_SUCCESS on success, second is true if RDMA is supported

std::error_code framework::net::dpdk_init_eal(
const DpdkConfig &config,
)#

Initialize DPDK EAL with configuration parameters

Parameters:

config[in] DPDK configuration parameters

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_cleanup_eal()#

Cleanup DPDK EAL resources

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_set_port_mtu(
uint16_t port_id,
uint16_t mtu,
)#

Set MTU size for DPDK ethernet port

Parameters:
  • port_id[in] DPDK port identifier

  • mtu[in] MTU size in bytes

Returns:

std::error_code indicating success or specific error condition

DpdkPortState framework::net::dpdk_try_configure_port(
uint16_t port_id,
uint16_t rxq_count,
uint16_t txq_count,
bool enable_accurate_send_scheduling,
)#

Configure DPDK ethernet port.

Parameters:
  • port_id[in] DPDK port identifier

  • rxq_count[in] Number of RX queues

  • txq_count[in] Number of TX queues

  • enable_accurate_send_scheduling[in] Whether to enable accurate send scheduling

Returns:

DpdkPortState indicating configuration result

std::error_code framework::net::dpdk_try_tune_virtual_memory()#

Tune virtual memory settings for optimal network performance

Optimizes vm.zone_reclaim_mode and vm.swappiness kernel parameters for DPDK network operations. Sets both parameters to 0 for best performance.

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_enable_flow_rule_isolation(
uint16_t port_id,
)#

Restrict ingress traffic for DPDK ethernet port

Enables flow isolation on the specified port to restrict ingress traffic. This allows only explicitly configured flows to reach the application.

Parameters:

port_id[in] DPDK port identifier

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_disable_ethernet_flow_control(
uint16_t port_id,
)#

Disable Ethernet flow control for DPDK port

Disables flow control on the specified port by setting the mode to RTE_ETH_FC_NONE. This prevents the port from sending or responding to flow control frames.

Parameters:

port_id[in] DPDK port identifier

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_start_eth_dev(uint16_t port_id)#

Start DPDK ethernet device

Starts the specified DPDK ethernet port and enables packet processing. The port must be configured before calling this function.

Parameters:

port_id[in] DPDK port identifier

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_stop_eth_dev(uint16_t port_id)#

Stop DPDK ethernet device

Stops the specified DPDK ethernet port and disables packet processing. This function can be called safely even if the port is already stopped.

Parameters:

port_id[in] DPDK port identifier

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_setup_tx_queue(
uint16_t port_id,
uint16_t txq_id,
uint16_t txq_size,
)#

Setup DPDK TX queue

Sets up a TX queue for the specified DPDK ethernet port. The port must be configured before calling this function.

Parameters:
  • port_id[in] DPDK port identifier

  • txq_id[in] TX queue identifier

  • txq_size[in] TX queue size (number of descriptors)

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_calculate_timestamp_offsets(
int &timestamp_offset,
uint64_t &timestamp_mask,
)#

Calculate timestamp offsets for DPDK

Registers dynamic fields and flags for timestamp-based packet transmission. Calculates the timestamp offset and mask required for accurate send scheduling.

Parameters:
  • timestamp_offset[out] Offset for timestamp field in mbuf

  • timestamp_mask[out] Mask for timestamp flag

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_check_pcie_max_read_request_size(
std::string_view pci_address,
PcieMrrs expected_mrrs_value,
)#

Check PCIe Maximum Read Request Size

Uses sysfs to read the current PCIe MRRS and compare it with the expected value. Logs a warning if the current value doesn’t match the expected value, which may impact network performance.

Parameters:
  • pci_address[in] PCI address in format “XXXX:XX:XX.X”

  • expected_mrrs_value[in] Expected MRRS value

Returns:

std::error_code success if values match, pcie_verify_mismatch if different

Log DPDK ethernet port link information

Retrieves and logs the current link status, speed, and duplex mode for the specified DPDK port.

Parameters:

port_id[in] DPDK port identifier

Returns:

std::error_code indicating success or specific error condition

Check if DPDK ethernet port link is up

Retrieves the link status for the specified DPDK port and checks if the link is up.

Parameters:

port_id[in] DPDK port identifier

Returns:

std::error_code success if link is up, link_down if link is down, or other error on failure

std::error_code framework::net::dpdk_log_stats(uint16_t port_id)#

Log DPDK ethernet port statistics

Retrieves and logs detailed statistics including packet counts, byte counts, and error counts for the specified DPDK port on a single line.

Parameters:

port_id[in] DPDK port identifier

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_validate_mellanox_driver(
uint16_t port_id,
)#

Validate Mellanox driver for DPDK ethernet port

Checks device driver information for the specified DPDK port and validates it is a supported Mellanox driver. Also retrieves the network interface name.

Parameters:

port_id[in] DPDK port identifier

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_create_mempool(
std::string_view name,
uint16_t port_id,
uint32_t num_mbufs,
uint32_t mtu_size,
HostPinned host_pinned,
rte_mempool **mempool,
)#

Create DPDK mempool with optional host memory pinning

Creates a DPDK mempool for packet buffers with configurable memory type. When host pinning is enabled, uses CUDA host-pinned memory for better GPU-CPU transfer performance. Calculates buffer sizes based on MTU and uses proper alignment for GPU operations.

Parameters:
  • name[in] Unique name for the mempool (DPDK copies internally)

  • port_id[in] DPDK port ID to determine NUMA socket

  • num_mbufs[in] Number of mbufs in the mempool

  • mtu_size[in] MTU size for buffer calculations

  • host_pinned[in] Whether to use host-pinned memory

  • mempool[out] Pointer to store the created mempool

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_destroy_mempool(
rte_mempool *mempool,
)#

Destroy DPDK mempool and free associated resources

Safely destroys a DPDK mempool created with dpdk_create_mempool. Handles cleanup of both regular and host-pinned memory pools.

Parameters:

mempool[in] Pointer to the mempool to destroy (can be nullptr)

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_eth_send(
std::span<const std::span<const uint8_t>> messages,
const EthernetHeader &eth_header,
rte_mempool *mempool,
uint16_t queue_id,
uint16_t port_id,
uint32_t max_retry_count = DEFAULT_MAX_RETRY_COUNT,
)#

Send multiple Ethernet packets using DPDK

Allocates mbufs in bulk from the mempool, copies the Ethernet header and message data for each packet, and transmits them using rte_eth_tx_burst with retry logic. Any unsent mbufs are automatically freed by this function.

Parameters:
  • messages[in] 2D span of message data to send (each inner span is one message)

  • eth_header[in] Ethernet header to prepend to each message

  • mempool[in] DPDK mempool for mbuf allocation

  • queue_id[in] TX queue identifier

  • port_id[in] DPDK port identifier

  • max_retry_count[in] Maximum number of retries when no progress is made

Returns:

std::error_code indicating success or specific error condition

std::error_code framework::net::dpdk_eth_send_mbufs(
const std::span<rte_mbuf*> mbufs,
uint16_t queue_id,
uint16_t port_id,
uint32_t max_retry_count = DEFAULT_MAX_RETRY_COUNT,
)#

Send pre-allocated mbufs using DPDK

Transmits a span of pre-allocated and prepared mbufs using rte_eth_tx_burst. This function provides zero-copy transmission for high-performance scenarios. The caller is responsible for mbuf allocation and data preparation. Any unsent mbufs are automatically freed by this function.

Note

This is a high-performance path - mbufs should be pre-allocated and configured for optimal throughput

Note

Maximum burst size is limited by DPDK’s uint16_t constraints

Parameters:
  • mbufs[in] Span of pre-allocated mbufs to send

  • queue_id[in] TX queue identifier

  • port_id[in] DPDK port identifier

  • max_retry_count[in] Maximum number of retries when no progress is made

Returns:

std::error_code indicating success or specific error condition

inline const DpdkErrorCategory &framework::net::dpdk_category(
) noexcept#

Get the singleton instance of the DPDK error category

Returns:

Reference to the DPDK error category

inline std::error_code framework::net::make_error_code(
const DpdkErrc errc,
) noexcept#

Create an error_code from a DpdkErrc value

Parameters:

errc[in] The DPDK error code

Returns:

A std::error_code representing the DPDK error

constexpr bool framework::net::is_success(
const DpdkErrc errc,
) noexcept#

Check if a DpdkErrc represents success

Parameters:

errc[in] The error code to check

Returns:

true if the error code represents success, false otherwise

inline bool framework::net::is_dpdk_success(
const std::error_code &errc,
) noexcept#

Check if an error_code represents DPDK success

Parameters:

errc[in] The error code to check

Returns:

true if the error code represents DPDK success, false otherwise

inline const char *framework::net::get_error_name(
const DpdkErrc errc,
) noexcept#

Get the name of a DpdkErrc enum value

Parameters:

errc[in] The error code

Returns:

The enum name as a string

inline const char *framework::net::get_error_name(
const std::error_code &ec,
) noexcept#

Get the name of a DpdkErrc from a std::error_code

Parameters:

ec[in] The error code

Returns:

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

std::vector<std::string> framework::net::discover_mellanox_nics()#

Discover Mellanox NICs in the system

Scans the system for Mellanox NICs by checking PCI vendor ID and device class. Returns PCI addresses suitable for DPDK allowlisting.

Returns:

Vector of PCI addresses (e.g., “0000:29:00.1”) for Mellanox ethernet controllers

framework::net::DECLARE_LOG_COMPONENT(
Net,
NetGeneral,
NetGpu,
NetDpdk,
NetDoca,
)#

Declare logging components for network subsystem.

template<typename ExceptionType = std::runtime_error, typename ...Args>
void framework::net::log_and_throw(
Net component,
std::format_string<Args...> format_string,
Args&&... args,
)#

Log error message and throw exception

Template Parameters:
  • ExceptionType – Exception type to throw (defaults to std::runtime_error)

  • Args – Variadic template arguments for format string

Parameters:
  • component[in] Net component for error logging

  • format_string[in] Format string for error message

  • args[in] Format string arguments

Throws:

ExceptionType – with formatted error message

int framework::net::launch_gpunetio_sender_kernel(
cudaStream_t stream,
const DocaTxQParams &txq,
)#

Launch kernel to send a single packet

Parameters:
  • stream[in] CUDA stream for kernel execution

  • txq[in] TX queue structure containing GPU handles

Returns:

0 on success, < 0 otherwise

int framework::net::launch_gpunetio_receiver_kernel(
cudaStream_t stream,
const DocaRxQParams &rxq,
uint32_t *gpu_exit_condition,
)#

Launch kernel to receive a single packet and block until received

Parameters:
  • stream[in] CUDA stream for kernel execution

  • rxq[in] RX queue structure containing GPU handles

  • gpu_exit_condition[in] GPU exit condition flag

Returns:

0 on success, < 0 otherwise

void framework::net::setup_logging()#

Setup logging for network sample applications

tl::expected<Arguments, std::string> framework::net::parse_arguments(
const NetSample sample_type,
const int argc,
const char **argv,
)#

Parse command line arguments with system validation

Performs the following operations:

  1. Parses command line arguments

  2. Validates CUDA device availability

  3. Discovers and validates Mellanox NICs

  4. Overrides NIC PCIe address if not specified

Parameters:
  • sample_type[in] Type of network sample (SENDER or RECEIVER)

  • argc[in] Number of command line arguments

  • argv[in] Array of command line argument strings

Returns:

Arguments on success, empty string if &#8212;help or &#8212;version shown, error message on failure

EnvConfig framework::net::create_net_env_config(
const NetSample sample_type,
const Arguments &args,
)#

Create a network environment configuration for sending or receiving

Parameters:
  • sample_type[in] Type of network sample (SENDER or RECEIVER)

  • args[in] Parsed command line arguments

Returns:

Configured EnvConfig for network operations

std::error_code framework::net::send_dpdk_message(
const Env &env,
const MacAddress &dest_mac,
)#

Send a message using DPDK-only mode (CPU-only, no GPU/DOCA)

Sends “Hello DPDK” message using the NIC’s MAC as source and the configured destination MAC from arguments.

Parameters:
  • env[in] Network environment (must be configured for DPDK-only mode)

  • dest_mac[in] Destination MAC address

Returns:

Error code (success if no error)

bool framework::net::cuda_memcpy_host_to_device(
void *dst,
const void *src,
const std::size_t size,
std::optional<cudaStream_t> stream,
) noexcept#

Copy data from host to device with error logging

If stream is provided, uses cudaMemcpyAsync (caller responsible for synchronization). If stream is not provided (nullopt), uses synchronous cudaMemcpy (data ready on return).

Parameters:
  • dst[in] Destination device pointer

  • src[in] Source host pointer

  • size[in] Number of bytes to copy

  • stream[in] Optional CUDA stream for async copy (if nullopt, uses synchronous copy)

Returns:

true on success, false on failure (error is logged)

bool framework::net::cuda_memcpy_device_to_host(
void *dst,
const void *src,
const std::size_t size,
std::optional<cudaStream_t> stream,
) noexcept#

Copy data from device to host with error logging

If stream is provided, uses cudaMemcpyAsync (caller responsible for synchronization). If stream is not provided (nullopt), uses synchronous cudaMemcpy (data ready on return).

Parameters:
  • dst[in] Destination host pointer

  • src[in] Source device pointer

  • size[in] Number of bytes to copy

  • stream[in] Optional CUDA stream for async copy (if nullopt, uses synchronous copy)

Returns:

true on success, false on failure (error is logged)

tl::expected<TestDpdkSetup, std::string> framework::net::configure_test_dpdk_port(
)#

Get a configured DPDK port and device for testing

This function discovers Mellanox NICs, opens and probes a DOCA device, gets the DPDK port ID, and configures the port for testing.

Returns:

Configured port and device on success, error message on failure

void framework::net::enable_sanitizer_compatibility()#

Enable sanitizer compatibility for processes with elevated capabilities

When a process has CAP_SYS_NICE (for real-time scheduling), it becomes non-dumpable by default for security. This prevents LeakSanitizer and other debugging tools from working. This function makes the process dumpable again when sanitizers are enabled.

bool framework::net::has_cuda_device()#

Check for CUDA device availability

Returns:

true if at least one CUDA device is available, false otherwise

bool framework::net::has_mellanox_nic()#

Check for Mellanox NIC availability

Returns:

true if at least one Mellanox NIC is available, false otherwise

struct Arguments#
#include <net_samples.hpp>

Command line arguments structure

Public Members

GpuDeviceId cuda_device_id = {0}#

CUDA device ID.

std::string nic_pcie_addr#

NIC PCIe address.

MacAddress mac_addr#

MAC address.

int timeout_seconds = {}#

Timeout in seconds (0 = no timeout)

bool cpu_only = {false}#

Use CPU-only DPDK mode (no GPU/DOCA)

struct DocaDeviceDeleter#
#include <net_test_helpers.hpp>

Custom deleter for DOCA device

Public Functions

void operator()(doca_dev *device) const noexcept#
class DocaRxQ#
#include <doca_rxq.hpp>

RAII wrapper for DOCA RX queue management

Provides automatic resource management for DOCA receive queues, including flow rule setup and cleanup.

Public Functions

DocaRxQ(
const DocaRxQConfig &config,
doca_gpu *gpu_dev,
doca_dev *ddev,
)#

Create and initialize a DOCA RX queue with flow rule

Parameters:
  • config[in] Configuration parameters for the RX queue and flow rule

  • gpu_dev[in] DOCA GPU device

  • ddev[in] DOCA device

Throws:

std::runtime_error – if queue or flow rule creation fails

const DocaRxQParams *params() const noexcept#

Get the underlying DOCA RX queue structure

Returns:

Pointer to the internal DocaRxQParams structure

struct DocaRxQConfig#
#include <doca_rxq.hpp>

Configuration structure for DocaRxQ creation

Public Members

std::string nic_pcie_addr#

NIC PCIe address (e.g., “0000:3a:00.0”)

MacAddress sender_mac_addr#

Sender MAC address for flow rule.

std::uint32_t max_pkt_num = {}#

Maximum number of packets in queue.

std::uint32_t max_pkt_size = {}#

Maximum packet size in bytes.

std::uint16_t ether_type = {}#

EtherType value for flow rule matching.

std::optional<std::uint16_t> vlan_tci#

Optional VLAN TCI (if not set, no VLAN matching in flow rule)

std::optional<DocaSemItems> sem_items#

Semaphore configuration (if not set, no semaphores are created)

struct DocaRxQParams#
#include <doca_types.hpp>

Receive queues objects

Public Members

doca_gpu *gpu_dev = {}#

GPUNetio handler associated to queues (read-only after init)

doca_dev *ddev = {}#

DOCA device handler associated to queues (read-only after init)

doca_ctx *eth_rxq_ctx = {}#

DOCA Ethernet receive queue context.

doca_eth_rxq *eth_rxq_cpu = {}#

DOCA Ethernet receive queue CPU handler.

doca_gpu_eth_rxq *eth_rxq_gpu = {}#

DOCA Ethernet receive queue GPU handler.

doca_gpu_semaphore *sem_cpu = {}#

DOCA semaphore CPU handler.

doca_gpu_semaphore_gpu *sem_gpu = {}#

DOCA semaphore GPU handler.

bool has_sem_items = {}#

Whether semaphore configuration is set.

DocaSemItems sem_items = {}#

Semaphore configuration (valid only if has_sem_items is true)

doca_mmap *pkt_buff_mmap = {}#

DOCA mmap to receive packet with DOCA Ethernet queue

void *gpu_pkt_addr = {}#

DOCA mmap GPU memory address.

void *cpu_pkt_addr = {}#

CPU accessible memory address.

int dmabuf_fd = {}#

GPU memory dmabuf descriptor.

std::uint16_t dpdk_queue_idx = {}#

DPDK queue index for flow rules.

doca_flow_port *port = {}#

DOCA Flow port.

doca_flow_pipe *rxq_pipe = {}#

DOCA Flow receive pipe.

doca_flow_pipe *root_pipe = {}#

DOCA Flow root pipe.

doca_flow_pipe_entry *root_udp_entry = {}#

DOCA Flow root entry.

rte_flow *dpdk_flow_rule = {}#

DPDK flow rule that needs cleanup.

std::uint32_t max_pkt_size = {}#

Max packet size to read.

std::uint32_t max_pkt_num = {}#

Max number of RX packets in CUDA receive kernel.

std::uint16_t dpdk_port_id = {}#

DPDK port ID for cleanup.

struct DocaSemItems#
#include <doca_types.hpp>

Semaphore configuration parameters

Public Members

std::uint32_t num_items = {}#

Number of semaphore items.

std::uint32_t item_size = {}#

Size of custom info per item.

class DocaTxQ#
#include <doca_txq.hpp>

RAII wrapper for DOCA TX queue management

Provides automatic resource management for DOCA transmit queues, ensuring proper cleanup on destruction.

Public Functions

DocaTxQ(
const DocaTxQConfig &config,
doca_gpu *gpu_dev,
doca_dev *ddev,
)#

Create and initialize a DOCA TX queue

Parameters:
  • config[in] Configuration parameters for the TX queue

  • gpu_dev[in] DOCA GPU device

  • ddev[in] DOCA device

Throws:

std::runtime_error – if queue creation fails

const DocaTxQParams *params() const noexcept#

Get access to the internal DocaTxQParams structure for CUDA kernel usage

Note

This method is intended for advanced usage with CUDA kernels

Returns:

Pointer to the internal DocaTxQParams structure

struct DocaTxQConfig#
#include <doca_txq.hpp>

Configuration structure for DocaTxQ creation

Public Members

std::string nic_pcie_addr#

NIC PCIe address (e.g., “0000:3a:00.0”)

MacAddress dest_mac_addr#

Destination MAC address.

std::uint32_t pkt_size = {}#

Packet size to send.

std::uint32_t pkt_num = {}#

Number of packets.

std::uint32_t max_sq_descr_num = {}#

Maximum number of send queue descriptors.

std::uint16_t ether_type = {}#

EtherType value for packet headers.

std::optional<std::uint16_t> vlan_tci#

Optional VLAN TCI (if set, insert 802.1Q tag with inner EtherType)

struct DocaTxQParams#
#include <doca_types.hpp>

Send queues objects

Public Members

doca_gpu *gpu_dev = {}#

GPUNetio handler associated to queues.

doca_dev *ddev = {}#

DOCA device handler associated to queues.

doca_ctx *eth_txq_ctx = {}#

DOCA Ethernet send queue context.

doca_eth_txq *eth_txq_cpu = {}#

DOCA Ethernet send queue CPU handler.

doca_gpu_eth_txq *eth_txq_gpu = {}#

DOCA Ethernet send queue GPU handler.

doca_pe *eth_txq_pe = {}#

DOCA progress engine for TX queue.

doca_mmap *pkt_buff_mmap = {}#

DOCA mmap to send packet with DOCA Ethernet queue.

void *gpu_pkt_addr = {}#

DOCA mmap GPU memory address.

int dmabuf_fd = {}#

GPU memory dmabuf descriptor.

int txq_id = {}#

TX queue ID.

doca_flow_port *port = {}#

DOCA Flow port.

doca_buf_arr *buf_arr = {}#

DOCA buffer array object around GPU memory buffer.

doca_gpu_buf_arr *buf_arr_gpu = {}#

DOCA buffer array GPU handle.

std::uint32_t pkt_size = {}#

Packet size to send.

std::uint32_t num_packets = {}#

Number of TX packets in CUDA send kernel (max depdends on GPU memory)

std::uint32_t inflight_sends = {}#

Number of inflight sends in queue (should not exceeed descriptor count)

struct DpdkConfig#
#include <dpdk_types.hpp>

DPDK configuration parameters

Public Members

std::string app_name#

Application name for DPDK EAL.

std::string file_prefix#

File prefix for DPDK shared files (&#8212;file-prefix)

std::optional<std::uint32_t> dpdk_core_id#

DPDK core ID for main lcore (-l and &#8212;main-lcore=)

bool verbose_logs = {}#

Enable verbose logging (&#8212;log-level=,8 and &#8212;log-level=pmd.net.mlx5:8)

bool enable_rt_priority_for_lcores = {}#

Enable real-time priority (SCHED_FIFO with priority 95) for DPDK lcores

class DpdkErrorCategory : public std::error_category#
#include <dpdk_types.hpp>

Custom error category for DPDK errors

This class provides human-readable error messages and integrates DPDK 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 DPDK 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

struct DpdkTxQConfig#
#include <dpdk_txq.hpp>

Configuration structure for DpdkTxQueue creation

Public Members

std::uint16_t txq_size = {}#

TX queue size (number of descriptors)

class DpdkTxQueue#
#include <dpdk_txq.hpp>

RAII wrapper for DPDK TX queue management

Provides automatic resource management for DPDK transmit queues, ensuring proper cleanup on destruction. Manages a single TX queue on a DPDK port and provides methods for sending packets.

Public Functions

DpdkTxQueue(
std::uint16_t port_id,
std::uint16_t txq_id,
const DpdkTxQConfig &config,
)#

Create and initialize a DPDK TX queue

Sets up a TX queue for the specified DPDK ethernet port using dpdk_setup_tx_queue. The port must be configured before calling this constructor.

Parameters:
  • port_id[in] DPDK port identifier

  • txq_id[in] TX queue identifier

  • config[in] Configuration parameters for the TX queue

Throws:

std::runtime_error – if queue setup fails

std::error_code send(
std::span<const std::span<const std::uint8_t>> messages,
const EthernetHeader &eth_header,
rte_mempool *mempool,
std::uint32_t max_retry_count = DEFAULT_MAX_RETRY_COUNT,
) const#

Send multiple Ethernet packets using DPDK

Allocates mbufs in bulk from the mempool, copies the Ethernet header and message data for each packet, and transmits them using the configured TX queue. Any unsent mbufs are automatically freed.

Parameters:
  • messages[in] 2D span of message data to send (each inner span is one message)

  • eth_header[in] Ethernet header to prepend to each message

  • mempool[in] DPDK mempool for mbuf allocation

  • max_retry_count[in] Maximum number of retries when no progress is made

Returns:

std::error_code indicating success or specific error condition

std::error_code send_mbufs(
std::span<rte_mbuf*> mbufs,
std::uint32_t max_retry_count = DEFAULT_MAX_RETRY_COUNT,
) const#

Send pre-allocated mbufs using DPDK

Transmits a span of pre-allocated and prepared mbufs using the configured TX queue. The caller is responsible for mbuf allocation and data preparation. Any unsent mbufs are automatically freed.

Parameters:
  • mbufs[in] Span of pre-allocated mbufs to send

  • max_retry_count[in] Maximum number of retries when no progress is made

Returns:

std::error_code indicating success or specific error condition

inline std::uint16_t port_id() const noexcept#

Get the DPDK port ID for this TX queue

Returns:

DPDK port identifier

inline std::uint16_t queue_id() const noexcept#

Get the TX queue ID

Returns:

TX queue identifier

class Env#
#include <env.hpp>

RAII wrapper for DPDK and DOCA environment management

Provides automatic resource management for the entire networking environment, including DPDK EAL initialization, GPU device setup, and NIC management. Validates system requirements before initialization.

Public Functions

explicit Env(const EnvConfig &config)#

Create and initialize the networking environment

Performs the following initialization steps:

  1. Validates CUDA device count and GPU device ID

  2. Validates Mellanox NICs availability and configuration

  3. Initializes DPDK EAL

  4. Creates and initializes GPU device

  5. Creates and initializes NIC with queues

Parameters:

config[in] Environment configuration parameters

Throws:
  • std::runtime_error – if initialization fails

  • std::invalid_argument – if configuration is invalid

bool has_gpu() const noexcept#

Check if GPU device is available

Returns:

true if GPU device was created, false if running in DPDK-only mode

const Gpu &gpu() const#

Get the GPU device

Throws:

std::runtime_error – if no GPU device was created (DPDK-only mode)

Returns:

Reference to the GPU device

const Nic &nic() const noexcept#

Get the NIC device

Returns:

Reference to the NIC device

const DpdkConfig &dpdk_config() const noexcept#

Get the DPDK configuration used

Returns:

Reference to the DPDK configuration

bool is_initialized() const noexcept#

Check if the environment is properly initialized

Returns:

true if environment is initialized, false otherwise

struct EnvConfig#
#include <env.hpp>

Configuration structure for environment initialization

Public Members

DpdkConfig dpdk_config#

DPDK configuration parameters.

NicConfig nic_config#

NIC configuration parameters.

GpuDeviceId gpu_device_id = {0}#

GPU device ID to use.

class EthernetHeader#
#include <dpdk_types.hpp>

Ethernet frame header

Represents a standard Ethernet frame header with destination MAC, source MAC, and EtherType fields.

Public Functions

inline EthernetHeader(
const MacAddress src_mac,
const MacAddress dst_mac,
const std::uint16_t ether_type,
std::optional<std::uint16_t> vlan_tci = std::nullopt,
)#

Construct Ethernet header with specified parameters

Parameters:
  • src_mac[in] Source MAC address

  • dst_mac[in] Destination MAC address

  • ether_type[in] EtherType value (e.g., 0x0800 for IPv4)

  • vlan_tci[in] Optional VLAN tag control information (in host byte order)

inline const MacAddress &src_mac() const#

Get source MAC address

Returns:

Source MAC address

inline const MacAddress &dest_mac() const#

Get destination MAC address

Returns:

Destination MAC address

inline std::uint16_t ether_type() const#

Get EtherType value

Returns:

EtherType value

inline const std::optional<std::uint16_t> &vlan_tci() const#

Get optional VLAN TCI

Returns:

VLAN TCI if present

inline bool has_vlan() const#

Whether a VLAN tag should be present

Returns:

True if a VLAN tag is configured and should be emitted, false otherwise

bool operator==(const EthernetHeader &other) const = default#

Check if Ethernet header is equal to another header

Parameters:

other[in] The other Ethernet header to compare with

Returns:

True if the headers are equal, false otherwise

Public Static Attributes

static constexpr std::size_t NUM_BYTES = 14#

Ethernet header size in bytes.

class Gpu#
#include <gpu.hpp>

RAII wrapper for DOCA GPU device management

Provides automatic resource management for DOCA GPU devices, including PCI bus ID resolution and device initialization.

Public Functions

explicit Gpu(GpuDeviceId gpu_device_id)#

Create and initialize a DOCA GPU device

Parameters:

gpu_device_id[in] CUDA device ID to initialize

Throws:
  • std::runtime_error – if GPU device creation fails

  • std::invalid_argument – if GPU device ID is invalid

const std::string &pci_bus_id() const noexcept#

Get the PCI bus ID for this GPU device

Returns:

PCI bus ID string (e.g., “0000:3b:00.0”)

doca_gpu *get() const noexcept#

Get the underlying DOCA GPU device pointer

Returns:

Pointer to the DOCA GPU device

class GpuDeviceId#
#include <gpu.hpp>

Strongly-typed wrapper for GPU device identifiers

Prevents accidental usage of raw integers. Non-negative values are enforced at compile-time by using uint32_t constructor parameter.

Public Functions

inline explicit constexpr GpuDeviceId(const uint32_t id) noexcept#

Create a GPU device identifier

Parameters:

id[in] CUDA device ID (inherently non-negative)

inline constexpr int value() const noexcept#

Get the underlying device ID value

Returns:

Device ID as integer

constexpr bool operator==(
const GpuDeviceId &other,
) const noexcept = default#

Equality comparison

Parameters:

other[in] GPU device ID to compare against

Returns:

True if device IDs are equal, false otherwise

struct MacAddress#
#include <dpdk_types.hpp>

Strongly typed MAC address

Represents a 6-byte Ethernet MAC address with type safety.

Public Functions

std::string to_string() const#

Convert MAC address to string representation

Returns:

String in format “XX:XX:XX:XX:XX:XX”

bool is_zero() const#

Check if MAC address is zero (all bytes are 0x00)

Returns:

True if all bytes are zero

bool operator==(const MacAddress &other) const = default#

Check if MAC address is equal to another MAC address

Parameters:

other[in] The other MAC address to compare with

Returns:

True if the MAC addresses are equal, false otherwise

Public Members

std::array<std::uint8_t, ADDRESS_LEN> bytes = {}#

MAC address bytes.

Public Static Functions

static tl::expected<MacAddress, std::string> from_string(
const std::string_view mac_str,
)#

Create MAC address from string

Parameters:

mac_str[in] MAC address string in format “XX:XX:XX:XX:XX:XX”

Returns:

MAC address on success, error message on failure

Public Static Attributes

static constexpr std::size_t ADDRESS_LEN = 6U#

MAC address length.

class Mempool#
#include <mempool.hpp>

RAII wrapper for DPDK mempool management

Provides automatic resource management for DPDK mempools, ensuring proper cleanup on destruction. Supports both regular and host-pinned memory configurations.

Public Functions

Mempool(std::uint16_t port_id, const MempoolConfig &config)#

Create and initialize a DPDK mempool

Parameters:
  • port_id[in] DPDK port ID to determine NUMA socket

  • config[in] Configuration parameters for the mempool

Throws:
  • std::invalid_argument – if configuration parameters are invalid

  • std::runtime_error – if mempool creation fails

rte_mempool *dpdk_mempool() const noexcept#

Get access to the underlying DPDK mempool structure

Note

This method is intended for advanced usage with DPDK operations

Returns:

Pointer to the internal rte_mempool structure

struct MempoolConfig#
#include <mempool.hpp>

Configuration structure for Mempool creation

Public Members

std::string name#

Unique name for the mempool.

std::uint32_t num_mbufs = {}#

Number of mbufs in the mempool.

std::uint32_t mtu_size = {}#

MTU size for buffer calculations.

HostPinned host_pinned = {}#

Whether to use host-pinned memory.

class Nic#
#include <nic.hpp>

RAII wrapper for DOCA NIC device management

Provides automatic resource management for DOCA network devices, including MAC address resolution, DPDK port mapping, and queue management.

Public Functions

explicit Nic(
const NicConfig &config,
std::optional<doca_gpu*> gpu_dev = std::nullopt,
)#

Create and initialize a DOCA NIC device with queues

Parameters:
  • config[in] Configuration parameters for the NIC and its queues

  • gpu_dev[in] DOCA GPU device for queue creation (optional, required only for DOCA queues)

Throws:
  • std::runtime_error – if NIC device creation fails

  • std::invalid_argument – if configuration parameters are invalid

const std::string &pci_address() const noexcept#

Get the PCI address for this NIC

Returns:

PCI address string (e.g., “0000:3a:00.0”)

const MacAddress &mac_address() const noexcept#

Get the MAC address for this NIC

Returns:

Strongly typed MAC address

std::uint16_t dpdk_port_id() const noexcept#

Get the DPDK port ID for this NIC

Returns:

DPDK port ID

doca_dev *get() const noexcept#

Get the underlying DOCA device pointer

Returns:

Pointer to the DOCA device

bool is_cx6_device() const noexcept#

Check if this is a CX-6 device

Returns:

True if CX-6 device, false otherwise

tl::expected<bool, std::string> is_rdma_supported() const noexcept#

Check if NIC supports RDMA operations

Verifies that this NIC can perform RDMA operations, which is required for GPU-accelerated RDMA datapath. This checks if the device supports RDMA write operations.

Returns:

True if RDMA is supported, error message on failure

const std::vector<DocaTxQ> &doca_tx_queues() const noexcept#

Get the DOCA TX queues

Returns:

Reference to vector of DOCA TX queues

const std::vector<DocaRxQ> &doca_rx_queues() const noexcept#

Get the DOCA RX queues

Returns:

Reference to vector of DOCA RX queues

const DocaTxQ &doca_tx_queue(std::size_t index) const#

Get a specific DOCA TX queue by index

Parameters:

index[in] Queue index

Throws:

std::out_of_range – if index is invalid

Returns:

Reference to the DOCA TX queue

const DocaRxQ &doca_rx_queue(std::size_t index) const#

Get a specific DOCA RX queue by index

Parameters:

index[in] Queue index

Throws:

std::out_of_range – if index is invalid

Returns:

Reference to the DOCA RX queue

const std::vector<DpdkTxQueue> &dpdk_tx_queues() const noexcept#

Get the DPDK TX queues

Returns:

Reference to vector of DPDK TX queues

const DpdkTxQueue &dpdk_tx_queue(std::size_t index) const#

Get a specific DPDK TX queue by index

Parameters:

index[in] Queue index

Throws:

std::out_of_range – if index is invalid

Returns:

Reference to the DPDK TX queue

const std::vector<Mempool> &mempools() const noexcept#

Get the mempools

Returns:

Reference to vector of mempools

const Mempool &mempool(std::size_t index) const#

Get a specific mempool by index

Parameters:

index[in] Mempool index

Throws:

std::out_of_range – if index is invalid

Returns:

Reference to the mempool

std::error_code send(
std::size_t dpdk_txq_id,
std::size_t mempool_id,
std::span<const std::span<const std::uint8_t>> messages,
const EthernetHeader &eth_header,
std::uint32_t max_retry_count = DEFAULT_MAX_RETRY_COUNT,
) const#

Send multiple Ethernet packets using DPDK TX queue

Sends packets using the specified DPDK TX queue and mempool. Allocates mbufs in bulk from the specified mempool, copies the Ethernet header and message data for each packet, and transmits them using the specified queue.

Parameters:
  • dpdk_txq_id[in] DPDK TX queue index

  • mempool_id[in] Mempool index

  • messages[in] 2D span of message data to send (each inner span is one message)

  • eth_header[in] Ethernet header to prepend to each message

  • max_retry_count[in] Maximum number of retries when no progress is made

Throws:

std::out_of_range – if dpdk_txq_id or mempool_id is invalid

Returns:

std::error_code indicating success or specific error condition

std::error_code send_mbufs(
std::size_t dpdk_txq_id,
std::span<rte_mbuf*> mbufs,
std::uint32_t max_retry_count = DEFAULT_MAX_RETRY_COUNT,
) const#

Send pre-allocated mbufs using DPDK TX queue

Transmits a span of pre-allocated and prepared mbufs using the specified DPDK TX queue. The caller is responsible for mbuf allocation and data preparation. Any unsent mbufs are automatically freed by this function.

Parameters:
  • dpdk_txq_id[in] DPDK TX queue index

  • mbufs[in] Span of pre-allocated mbufs to send

  • max_retry_count[in] Maximum number of retries when no progress is made

Throws:

std::out_of_range – if dpdk_txq_id is invalid

Returns:

std::error_code indicating success or specific error condition

struct NicConfig#
#include <nic.hpp>

Configuration structure for NIC creation

Public Members

std::string nic_pcie_addr#

NIC PCIe address (e.g., “0000:3a:00.0”)

std::vector<DocaTxQConfig> doca_txq_configs#

DOCA TX queue configurations.

std::vector<DocaRxQConfig> doca_rxq_configs#

DOCA RX queue configurations.

std::vector<DpdkTxQConfig> dpdk_txq_configs#

DPDK TX queue configurations.

std::vector<MempoolConfig> mempool_configs#

Mempool configurations.

bool enable_accurate_send_scheduling = {false}#

Enable accurate send scheduling.

std::uint16_t max_mtu_size = {9216}#

Maximum MTU size in bytes (jumbo frame)

PcieMrrs pcie_mrrs = {PcieMrrs::Bytes4096}#

PCIe Maximum Read Request Size.

struct TestDpdkSetup#
#include <net_test_helpers.hpp>

Test setup result containing configured port and device pointers

Public Members

std::uint16_t port_id = {}#

Configured DPDK port ID.

DocaDevicePtr ddev#

DOCA device smart pointer.

std::string pcie_address#

PCIe address of the NIC.