Generated banner for Doca Gpunetio
Generated logo for Doca Gpunetio

Doca Gpunetio

NVIDIAOfficialCreated by NVIDIA

  • Skill
  • Tool integration
  • Software development
  • Apache-2.0
  • Medium risk

From the author

Use this skill when the user is doing hands-on DOCA GPUNetIO programming — wiring a CUDA kernel on an NVIDIA GPU to a doca-eth queue via doca_gpu_eth_rxq / doca_gpu_eth_txq, standing up the per-CUDA-device doca_gpu context, designing the persistent CUDA kernel that drains the GPU-visible queue, running the dual capability check (DOCA cap-query plus cudaGetDeviceProperties), registering cudaMalloc pools via doca_buf_arr_create_*, or debugging DOCA_ERROR_* returns from the GPUNetIO API. Trigger even when the user does not explicitly mention "DOCA GPUNetIO" or "persistent kernel" — typical implicit phrasings include "CUDA kernel reading packets directly from the NIC", "GPU-initiated networking on BlueField", "DOCA_ERROR_DRIVER on doca_gpu_create", "nvidia_peermem not loaded", "kernel-per-packet is too slow", or "which GPU supports GPU-side packet I/O". Refuse and route elsewhere for general CUDA programming, DOCA Ethernet queue bring-up, DOCA DPA, or DOCA install — those belong to other skills.
— the description by NVIDIA

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides specialized support for developers building applications that use the DOCA GPUNetIO library. It focuses on the integration between host-side C/C++ code and device-side CUDA kernels, specifically for scenarios involving GPU-initiated networking on BlueField DPU or ConnectX NIC environments. The skill covers the lifecycle of GPU-visible network queues, persistent kernel design, memory registration, and capability verification across both DOCA and CUDA layers.

What it does

  • Assists in wiring CUDA kernels to doca_gpu_eth_rxq and doca_gpu_eth_txq handles.
  • Guides the setup of per-CUDA-device doca_gpu contexts.
  • Provides patterns for persistent CUDA kernels that process packets directly from NIC queues.
  • Supports dual capability checking using DOCA cap-query and cudaGetDeviceProperties.
  • Details the registration of cudaMalloc pools via doca_buf_arr_create_*.
  • Helps diagnose and debug DOCA_ERROR_* codes specific to the GPUNetIO API.

When to use it

  • When developing applications that require direct packet processing on an NVIDIA GPU.
  • When troubleshooting GPUNetIO setup failures like DOCA_ERROR_DRIVER or missing nvidia_peermem.
  • When verifying compatibility between specific DOCA versions and CUDA toolkit versions.
  • When implementing the GPU Packet Processing reference application pattern.
  • When needing to resolve errors during the initialization of GPU-visible network queues.

Advantages

  • Provides a clear, structured approach to complex GPU-NIC integration tasks.
  • Ensures adherence to the DOCA Compatibility Policy for hardware and software versions.
  • Offers a systematic debugging framework for layered DOCA and CUDA errors.
  • Maintains a clean separation between GPUNetIO logic and general DOCA or CUDA programming.

Usage examples

“How do I get a CUDA kernel to receive packets directly from the NIC?”
The agent provides the persistent-kernel pattern and the GPU-side bring-up workflow to link a doca_gpu_eth_rxq to your CUDA kernel.
“Why does my GPUNetIO setup fail with DOCA_ERROR_NOT_SUPPORTED?”
The agent guides you through checking environment preconditions, specifically verifying if nvidia_peermem is loaded and GPUDirect RDMA is enabled.
“Can I run GPUNetIO on this GPU?”
The agent instructs you to perform a dual capability check using DOCA cap-query and cudaGetDeviceProperties to confirm hardware support.
“How do I move data between CUDA-allocated buffers and a DOCA queue?”
The agent explains the process of using cudaMalloc for buffer pools and registering them with DOCA via doca_buf_arr_create_* before starting the context.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/nvidia/doca-gpunetio/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip doca-gpunetio.zip -d .agents/skills

Documentation by NVIDIA

DOCA GPUNetIO

Examples

  • "CUDA kernel reading packets directly from the NIC." — this is in scope. Stay on doca_gpu_eth_rxq / _txq and the persistent kernel; do not rewrite it as host-CPU Ethernet.

  • "DOCA_ERROR_DRIVER on doca_gpu_create." — check CUDA device match and dmabuf / nvidia-peermem registration before changing queue type.

Instructions

Follow Loading order below. Open the tasks companion for configure / build / run. Open the capabilities companion for GPU vs host path selection. Do not open every companion file.

Where to start: This skill assumes DOCA is already installed, the CUDA toolkit is installed and matched to the DOCA install, and the user is doing hands-on GPUNetIO work — i.e. wiring a DOCA network queue into a CUDA kernel on an NVIDIA GPU. Open the tasks companion if the user wants to do something (configure / build / modify / run / test / debug); open the capabilities companion when the question is what can GPUNetIO express on this version + this GPU. If the user has not installed DOCA yet, route to doca-setup/SKILL.md first; if the user has not set up the underlying Ethernet RX/TX queues yet, that is a DOCA Ethernet question — route to doca-eth/SKILL.md.

Example questions this skill answers well

The CLASSES of GPUNetIO questions this skill is built to answer, each with one worked example. The agent should treat the class as the load-bearing piece — the worked example is a single instance.

  • "How do I get a CUDA kernel to receive packets directly from the NIC?" — worked example: "persistent kernel on one GPU reads packets from a doca_gpu_eth_rxq built on top of a representor doca_eth_rxq and counts them per-flow". Answered by the persistent-kernel pattern in

    Capabilities and modes

    • the GPU-side bring-up workflow in

    configure.

  • "Can I run GPUNetIO on this GPU?" — worked example: "my host has one Ampere card and one Turing card; which one supports GPU-initiated networking?". Answered by the dual capability-discovery rule (DOCA cap-query AND cudaGetDeviceProperties against the CUDA device ordinal) in

    Capabilities and modes

    • the device-enumeration step in

    configure.

  • "Why does my GPUNetIO setup fail with DOCA_ERROR_NOT_SUPPORTED even though doca-eth came up fine?" — worked example: "nvidia_peermem is not loaded so GPUDirect RDMA is unavailable". Answered by the env preconditions in ## Safety policy

    • the env checklist in

    configure step 1.

  • "How do I move data between CUDA-allocated buffers and a DOCA queue?" — worked example: "use cudaMalloc for the receive buffer pool and register it with DOCA via doca_buf_arr_create_* before starting the context". Answered by the CUDA-allocator

    • DOCA-registration overlay in

    Safety policy

    • the buffer-prep step in

    configure step 4.

  • "Is the GPUNetIO API I'm reading about on my installed DOCA + CUDA combination?" — worked example: "is the persistent-kernel helper available with the CUDA toolkit version I have?". Answered by the version-compatibility overlay in

    Version compatibility

    which cross-links the canonical detection chain in doca-version/SKILL.md and adds the GPUNetIO-specific DOCA must match CUDA overlay.

  • "What does this DOCA_ERROR_* from a GPUNetIO call mean and which layer caused it?" — worked example: "DOCA_ERROR_DRIVER on doca_gpu_*_create — is it DOCA, CUDA, or the underlying doca-eth queue?". Answered by the GPUNetIO overlay on the cross-library taxonomy in

    Error taxonomy

    • the layered ladder in

    debug that escalates to

    doca-debug/SKILL.md.

Audience

This skill serves external developers building applications that consume the DOCA GPUNetIO library — i.e., users whose code calls doca_gpu_* from host C/C++ to stand up the per-GPU context and the GPU-visible queue handles, and whose CUDA kernel (.cu translation unit) uses those handles from device code to submit / receive packets. The canonical target shape is the GPU Packet Processing reference application: a CUDA persistent kernel on an NVIDIA GPU that polls a GPU-visible RX queue and processes packets in-place on the GPU. It is not for NVIDIA developers contributing to DOCA GPUNetIO itself.

Language scope. DOCA GPUNetIO ships as a C / CUDA library with pkg-config module name doca-gpunetio. The host-side API is C; the device-side API is CUDA C++ used inside a .cu kernel. The shipped samples and the GPU Packet Processing reference application are written in C + CUDA C++ (NVIDIA's choice). Other-language consumers are limited in practice — the device-side API has no FFI escape hatch because the kernel must be a CUDA translation unit — but a Rust / Go / Python host-side wrapper that drives the host-side doca_gpu_* setup and launches a CUDA kernel built separately is still useful, and the skill keeps the lifecycle, capability-discovery, env-precondition, and error-taxonomy guidance language-neutral.

When to load this skill

Load this skill when the user is doing hands-on DOCA GPUNetIO work, in any host language plus CUDA. Concretely:

  • Initializing a doca_gpu against a specific CUDA device ordinal on a host with one or more NVIDIA GPUs.

  • Creating a GPU-visible queue handle (doca_gpu_eth_rxq, doca_gpu_eth_txq) on top of an existing doca_eth_rxq / doca_eth_txq from DOCA Ethernet, and passing the handle into a CUDA kernel for device-side use.

  • Writing or modifying the persistent CUDA kernel that drains the GPU-visible RX queue in a long-running loop (the canonical GPU Packet Processing shape).

  • Allocating GPU buffers via cudaMalloc and registering them with DOCA via the doca_buf_arr_create_* family before doca_ctx_start().

  • Checking which GPUNetIO features are supported on the active doca_devinfo (DOCA cap-query family) AND on the candidate CUDA device (cudaGetDeviceProperties and CUDA-driver-version checks).

  • Debugging a DOCA_ERROR_* returned from a GPUNetIO call — in particular disambiguating DOCA capability missing from CUDA device too old from nvidia_peermem not loaded from CUDA driver + DOCA version skew.

  • Designing host-side bindings for non-C languages that drive a CUDA kernel they built separately — the env-precondition and capability-discovery rules in this skill still apply.

Do not load this skill for general DOCA orientation, install of DOCA or the CUDA toolkit, the underlying DOCA Ethernet queue setup, or non-GPUNetIO library questions. For those, route through doca-public-knowledge-map/SKILL.md to the matching upstream guide.

What this skill provides

This is a thin loader. The body keeps only the orientation needed to pick the right next file. The substantive GPUNetIO-specific material lives in two companion files:

  • the capabilities companion — what GPUNetIO can express on this version

    • this GPU: the doca_gpu per-device context, the GPU-visible RX / TX queue handles layered on doca-eth, the persistent CUDA-kernel pattern as the default usage shape, the capability-query surface (the doca-eth doca_eth_rxq_cap_is_type_supported / doca_eth_rxq_cap_get_* family in doca_eth_rxq.h, plus the matching doca_eth_txq_cap_* family, on the DOCA side, plus cudaGetDeviceProperties on the CUDA side), the GPUNetIO error taxonomy mapped onto the cross-library DOCA_ERROR_* set, the observability surface (CUDA-side counters + DOCA-side per-task completion), and the safety policy that gates env preconditions (CUDA + DOCA version match, dmabuf or nvidia-peermem registration).

  • the tasks companion — step-by-step workflows for the six in-scope GPUNetIO verbs: configure, build, modify, run, test, debug. Plus a ## rollback overlay (GPUNetIO-specific five-step teardown that signals the persistent kernel to drain, unregisters GPU buffers in reverse-register order, and leaves the parent doca-eth queue intact) and the 5-phase universal debug-loop instantiation appended to ## debug. Plus a Deferred task verbs block that points out-of-scope questions at the right next skill.

The skill assumes a host where DOCA is already installed at the standard location, an NVIDIA GPU is physically present, the CUDA toolkit is installed and its version is matched to the DOCA install per the DOCA Compatibility Policy, and the underlying DOCA Ethernet RX/TX queues are already configured (this skill sits on top of doca-eth, not below it). It does not cover installing DOCA or the CUDA toolkit — that path goes through doca-setup/SKILL.md.

What this skill deliberately does not ship

This skill is agent guidance, not a samples or templates bundle. To keep the boundary clean, it deliberately does not contain — and pull requests should not add:

  • Pre-written DOCA GPUNetIO application source code or CUDA kernel source, in any language. The verified GPUNetIO source is the shipped C + CUDA samples at /opt/mellanox/doca/samples/doca_gpunetio/ and the GPU Packet Processing reference application. The agent's job is to route the user to those files and prescribe a minimum-diff modification on them via the universal modify-a-sample workflow in doca-programming-guide/SKILL.md, layered with the GPUNetIO-specific overrides in

    modify.

  • Standalone build manifests (meson.build, CMakeLists.txt, …) parked inside the skill. The agent constructs the build manifest in the user's project directory against the user's installed DOCA + CUDA toolkit, where pkg-config --modversion doca-gpunetio, pkg-config --modversion doca-common, and nvcc --version form the version gate.

  • A samples/, bindings/, or reference/ subtree of any kind. A mock or incomplete artifact in this skill's tree, even one labeled "reference", is misleading: users will read it as buildable.

Loading order

  1. Read this skill first to confirm the user's question is in scope.

  2. For the GPUNetIO capability matrix, the doca_gpu per-device context, the persistent-kernel pattern, the dual capability query, the env-precondition policy, the error taxonomy, the observability surface, and the safety policy, see the capabilities companion.

  3. For step-by-step workflows — configure, build, modify, run, test, debug — see the tasks companion.

Both companion files cross-link to each other, doca-version/SKILL.md for the canonical DOCA version-handling rules (with the GPUNetIO overlay that DOCA must match CUDA), and doca-public-knowledge-map/SKILL.md whenever the right answer is "look it up in the public DOCA GPUNetIO guide, the DOCA Compatibility Policy, the CUDA toolkit docs, or the on-disk install layout" rather than "GPUNetIO-specific guidance".

  • doca-public-knowledge-map/SKILL.md — the routing table for every public DOCA documentation source and the on-disk layout of an installed DOCA package. The GPUNetIO public guide is at https://docs.nvidia.com/doca/sdk/DOCA-GPUNetIO/index.html; the GPU Packet Processing reference application is reachable from there. The CUDA toolkit and DOCA Compatibility Policy links live in the same routing table.

  • doca-setup/SKILL.md — env preparation, install verification, CUDA toolkit install / verification, and the I have no install yet path with the public NGC DOCA container. This skill assumes its preconditions are satisfied AND that CUDA is installed at a version that matches DOCA.

  • doca-version/SKILL.md — canonical DOCA version-handling rules. This skill's ## Version compatibility cross-links the four-way match rule and adds the GPUNetIO-specific DOCA-and-CUDA must match overlay per the DOCA Compatibility Policy.

  • doca-structured-tools-contract/SKILL.md — the bundle's structured-tools precedence rule (detect / prefer / fall back / report). The Command appendix in the tasks companion honors this contract.

  • doca-programming-guide/SKILL.md — general DOCA programming patterns shared by every library: the canonical pkg-config + meson build pattern, the universal modify-a-shipped-sample first-app workflow, the universal lifecycle, the cross-library DOCA_ERROR_* taxonomy, and the program-side debug order. This skill layers GPUNetIO specifics on top.

  • doca-debug/SKILL.md — the cross-cutting debug ladder (install / version / build / link / runtime / program / driver). GPUNetIO-specific debug (CUDA + DOCA version skew, nvidia_peermem missing, persistent-kernel silent hangs, CUDA-allocator + DOCA-registration mismatches) overlays on top of that ladder.

DOCA Ethernet is GPUNetIO's mandatory companion library: GPU-visible RX / TX queue handles are layered on top of doca_eth_rxq / doca_eth_txq from DOCA Ethernet. For the underlying queue setup, route to doca-eth/SKILL.md.

Files

TASKS.md

DOCA GPUNetIO workflows

Where to start: The verbs run configure → build → modify → run → test → debug. Skip ahead only when the user is already past a verb. The ## test verb is an iterative loop (single-packet smoke → persistent-kernel burst loop → multi-GPU scale-out → loop back if a precondition changes), not a one-shot pass — see the eval-loop overlay in ## test below.

Read this file when the loader sent you here from SKILL.md. For the GPUNetIO capability surface, the doca_gpu per-device context, the GPU-visible queue handles, the persistent-kernel pattern, the dual capability-query rule, the env-precondition matrix, the error taxonomy, the observability surface, and the safety policy, see CAPABILITIES.md. For the cross-library DOCA patterns layered under everything below (the universal lifecycle, the cross-library DOCA_ERROR_* taxonomy, the modify-a-shipped- sample workflow), see doca-programming-guide/SKILL.md.

Each verb below describes the shape of the workflow, not a copy-paste recipe. The agent's job is to walk the user through the steps in order, verifying preconditions before recommending the next call.

DOCA 3.5 field notes

GPU memory registration: dmabuf first, nvidia-peermem only as a fallback (DOCA 3.5 GPUNetIO installation and setup page). dmabuf is the default and preferred method; it needs Linux kernel 6.2 or later, libibverbs 1.14.44 or later, and the open NVIDIA kernel driver (nvidia-open; CUDA 12.5 or older must be installed with -m=kernel-open). Get the descriptor with doca_gpu_dmabuf_fd(); on success use doca_mmap_set_dmabuf_memrange(), otherwise doca_mmap_set_memrange(). Without dmabuf, doca_mmap_start() falls back to legacy registration through nvidia-peermem (sudo modprobe nvidia-peermem) and logs Registration using dmabuf is not supported, falling back to legacy registration, which is harmless if peermem is acceptable. A missing nvidia-peermem module is therefore only a problem when dmabuf is unavailable.

DOCA 3.5 public API changes (public GPUNetIO header, doca_gpunetio.h). Update code that uses the GPUNetIO Verbs API:

  • Stop reading QP/CQ fields directly from struct doca_gpu_verbs_qp. Use the new doca_gpu_verbs_get_qp_* getter family to obtain the underlying QP, send CQ, and receive CQ.

  • Use doca_gpu_verbs_req_notify_cq() for CQ notification instead of the previous notification path.

  • Use doca_gpu_nic_handler_to_string() when a NIC handler name is needed.

  • Update constant usage to the DOCA 3.5 DOCA_GPUNETIO_VERBS_* and DOCA_GPUNETIO_ETH_* families from the public header.

See the public GPUNetIO header for the exact declarations and constant families.

configure

Goal: stand up a doca_gpu context on a target CUDA device, layer GPU-visible queue handles on top of an already-configured doca-eth queue pair, and confirm both the DOCA side and the CUDA side are in a state where a persistent kernel can be launched.

Steps the agent should walk the user through:

  1. Confirm the env preconditions. Per the env-precondition matrix in CAPABILITIES.md ## Safety policy: nvcc --version returns a CUDA toolkit version listed as compatible with the installed DOCA release by the DOCA Compatibility Policy; GPU memory registration is available — dmabuf first (see DOCA 3.5 field notes below), and only when dmabuf is unavailable lsmod | grep nvidia_peermem shows the fallback module loaded (or sudo modprobe nvidia_peermem); nvidia-smi -L enumerates the candidate GPU; the underlying doca-eth queues exist (route to doca-eth/SKILL.md for the upstream verb). If ANY of these fails, this is an env / version problem to fix via doca-setup TASKS.md ## configure (doca-setup/TASKS.md#configure)

    • doca-version TASKS.md ## configure (doca-version/TASKS.md#configure), NOT a code change in the GPUNetIO program.

  2. Bring up doca-eth FIRST. GPUNetIO sits on top of doca-eth: the user must have a configured doca_eth_rxq (and doca_eth_txq if TX is in scope) on the target representor / PCIe device, with the doca-eth context at the right lifecycle stage for the GPUNetIO layer to attach. Per the layering rule in CAPABILITIES.md ## Capabilities and modes, the agent must NOT skip ahead to doca_gpu_* calls if doca-eth is not already up — that ordering is fixed for every version of GPUNetIO.

  3. Run dual capability discovery against the target device. Per the dual-axis rule in CAPABILITIES.md ## Capabilities and modes: on the DOCA side, run the doca-eth query doca_eth_rxq_cap_is_type_supported(devinfo, ...) from doca_eth_rxq.h (and the matching doca_eth_txq_cap_is_type_supported / doca_eth_*_cap_get_* sizing family) against the active doca_devinfo for the NIC — GPUNetIO exposes no cap_is_supported symbol of its own; on the CUDA side, run cudaGetDeviceProperties(devOrdinal) against the candidate CUDA device. Quote BOTH results back to the user. If either says not supported, that axis is the answer — do not proceed.

  4. Allocate the GPU payload pool and register it with DOCA. The receive payload pool lives in GPU memory: allocate via cudaMalloc (or the CUDA allocator the user's app already uses) on the target device, then register the buffer with DOCA via the doca_buf_arr_create_* family before starting the parent doca-eth context with doca_ctx_start(). Per the safety policy in CAPABILITIES.md ## Safety policy, a missing or out-of-order registration surfaces as DOCA_ERROR_BAD_STATE from the first device-side submit, not at create time.

  5. Create the doca_gpu context and the GPU-visible queue handles. Create one doca_gpu for the target GPU — doca_gpu_create(const char *gpu_bus_id, ...) takes the GPU's PCIe bus-id STRING (e.g. from nvidia-smi -L / cudaDeviceGetPCIBusId), not an integer device ordinal; then create the GPU-visible RX handle (doca_gpu_eth_rxq) on top of the existing doca_eth_rxq (and, if TX is in scope, the matching doca_gpu_eth_txq). Start the doca-eth context if it has not been started already. Per the lifecycle ordering in CAPABILITIES.md ## Safety policy, record the order so teardown happens in reverse: GPU-visible handle → doca_gpu → CUDA context → doca-eth queue.

  6. Sanity check before launching any CUDA kernel. Confirm with the user: which CUDA device ordinal the persistent kernel will run on; which doca-eth queue the GPU-visible handle is layered on; whether RX-only, TX-only, or both; how the persistent kernel will know when to exit (a host-side flag read from device memory is the canonical signal). If any of those are unclear, stop and ask — do not invent.

For the canonical DOCA universal lifecycle that underlies steps 2-5, see doca-programming-guide TASKS.md ## configure (doca-programming-guide/TASKS.md#configure). This skill adds the GPUNetIO overlay; do not re-explain the lifecycle here.

build

Goal: compile a GPUNetIO-using consumer (host-side C/C++ + at least one CUDA .cu translation unit) against the user's installed DOCA + CUDA toolkit, with pkg-config + nvcc as the joint sources of truth for include + link flags.

The build pattern for any DOCA C/C++ consumer is fully documented in doca-programming-guide TASKS.md ## build (doca-programming-guide/TASKS.md#build). GPUNetIO adds a CUDA layer on top: the device-side code lives in .cu files compiled by nvcc, and the link line pulls in both the DOCA libraries and the CUDA runtime. This skill carries only the GPUNetIO-specific overlay:

SlotValueWhy it matters
pkg-config module namedoca-gpunetioThe library's .pc file installed by the DOCA host packages
Include flagspkg-config --cflags doca-gpunetio + nvcc --include-path for CUDAResolves DOCA headers under whichever include directory pkg-config --cflags reports on this install (do not hardcode the include path — it can move across DOCA install profiles) and the CUDA runtime headers from the CUDA toolkit install
Link flagspkg-config --libs doca-gpunetio plus the CUDA runtime link line (-lcudart)Pulls in whatever pkg-config --libs resolves on this install (do not predict the -l<name> form by hand — .so basenames use underscores, .pc names use hyphens, and pkg-config is the only correct translator) and the CUDA runtime
Companion DOCA libsdoca-eth (mandatory; GPUNetIO is layered on top); doca-argp for arg parsing in samplesAdding doca-eth to the build is mandatory because every shipped GPUNetIO sample includes the underlying Ethernet queue setup
CUDA compile rule.cu translation units compiled by nvcc; host-side C/C++ compiled by the system compiler; linked togetherA common partial-build failure is compiling everything with the system C compiler — the .cu file silently degrades to host-only code and the device-side primitives never execute
Device-code build gateEvery .cu translation unit is compiled by nvcc, and cuobjdump on the resulting artifact confirms device code is presentA successful host link is not sufficient evidence that the persistent kernel was emitted
DOCA version gateCompare pkg-config --modversion doca-gpunetio with pkg-config --modversion doca-common; require them to match, never hardcode eitherCross-version build/runtime mixing breaks per CAPABILITIES.md ## Version compatibility
Minimum CUDA versionQuery with nvcc --version; cross-check against the DOCA Compatibility Policy linked from CAPABILITIES.md ## Version compatibilityMismatched CUDA + DOCA combos fail at link time or runtime with DOCA_ERROR_DRIVER

For non-C host-side consumers (Rust, Go, Python) that drive GPUNetIO setup and launch a CUDA kernel built separately, the host-side link line and version rules above still apply; the CUDA kernel itself is a separate compilation unit and is out of scope for this skill, but the nvcc version check is the load-bearing input the wrapper still needs.

modify

Goal: take the closest-fitting shipped DOCA GPUNetIO sample as the verified starting point and apply a minimum diff to make it match the user's intent, without rewriting from scratch.

The universal modify-a-shipped-sample workflow is in doca-programming-guide TASKS.md ## modify (doca-programming-guide/TASKS.md#modify); this skill provides the GPUNetIO-specific slot fill.

SlotWhat the agent asks the userGPUNetIO-specific consideration
1. Starting sampleWhich sample under /opt/mellanox/doca/samples/doca_gpunetio/? Or the GPU Packet Processing reference application?Match the user's intent (RX-only / TX-only / both; single-flow / multi-flow) to a sample whose code shape already matches. Do NOT bridge across the persistent-kernel boundary — a sample that uses a persistent kernel is the right base for any persistent-kernel app
2. Persistent kernel bodyWhich packet-processing logic goes inside the persistent kernel?The persistent-kernel body is the in-place edit point. The agent's anti-pattern alert: do NOT propose launching one CUDA kernel per packet — that defeats GPUNetIO entirely per CAPABILITIES.md ## Capabilities and modes
3. CUDA device ordinalWhich GPU is the persistent kernel pinned to? Single-GPU or multi-GPU?Per the per-GPU rule in CAPABILITIES.md ## Capabilities and modes, multi-GPU means one doca_gpu per device AND one persistent kernel per device — that is a re-architecture, not a tweak
4. RX-only vs TX-only vs bothWhich directions does the persistent kernel need?Each direction needs its own GPU-visible queue handle and its own underlying doca-eth queue; adding TX after RX is up means re-running cap-query for the TX side
5. Buffer pool sizingHow big is the GPU payload pool that backs the RX queue?Per the env-precondition matrix in CAPABILITIES.md ## Safety policy, the pool is allocated via cudaMalloc and registered with DOCA via doca_buf_arr_create_* BEFORE doca_ctx_start(); resizing means re-running the registration sequence
6. Termination signalHow does the persistent kernel know when to exit?A host-side flag read from device memory is the canonical signal; without it the kernel runs forever and doca_ctx_stop blocks. The agent must surface this on every modify pass

The agent emits an intent description + the six filled slots; the actual unified diff against the sample source is produced the way every other library skill in this bundle handles modify — the agent walks the user through the diff line-by-line against the sample source they read on disk, and has the user paste back the result for validation. The agent's anti-pattern alert: a "clean rewrite" from scratch is almost always slower to first green than a minimum-diff modify on a shipped GPUNetIO sample, and removes the user's ability to bisect against a known-good baseline.

run

Goal: actually launch the persistent kernel against the configured GPU-visible queue and confirm packets flow on the wire.

Steps the agent should walk the user through:

  1. Confirm the peer is generating traffic. GPUNetIO needs packets arriving at the doca-eth RX queue; running the persistent kernel against an empty queue produces a misleading 0% GPU util and looks like a hang. The agent must surface this on every first run.

  2. Launch the persistent kernel with the GPU-visible RX (and optionally TX) handle passed in as a kernel argument. The kernel is launched once and runs for the duration of the data-movement session; do not re-launch per batch. The block / thread sizing depends on the user's GPU per cudaGetDeviceProperties.

  3. Drive the host-side doca_pe_progress loop in parallel with the persistent kernel — the DOCA-side completions and the connection / lifecycle events still flow through the host PE even when the data plane is GPU-driven. A common silent-failure mode is forgetting the host-side PE drive and wondering why state transitions are not reported.

  4. Capture the structured log on first failure. Set DOCA_LOG_LEVEL=trace for the first run (see doca-debug CAPABILITIES.md ## Observability (doca-debug/CAPABILITIES.md#observability)); pair it with nvidia-smi -q -d UTILIZATION while the kernel runs to confirm the GPU is actually busy. A persistent kernel that reports 0% util is stuck on a queue drain.

For the runtime version + LD_LIBRARY_PATH cross-checks that underlie "the program built but does nothing", see doca-version TASKS.md ## run (doca-version/TASKS.md#run).

test

Goal: prove the configured GPUNetIO setup actually moves packets from the wire into the persistent kernel on the user's hardware, and that the env-precondition + capability set was sized right.

This is a loop, not a one-shot pass. Each iteration narrows either the env-precondition set, the capability set, the persistent-kernel design, or the buffer sizing. Termination and the iteration-identity tuple are defined once under Loop termination below.

Iteration shape:

  1. Single-packet smoke from the GPU side. Send ONE packet from a peer; confirm the persistent kernel observes one RX completion. If yes, advance. If no — and nvidia-smi reports the kernel is running — the GPU-visible RX handle is not actually layered on the doca-eth queue that the peer's traffic is hitting; re-run ## configure step 5.

  2. Persistent-kernel burst loop. Send 1000 packets in a burst; confirm the persistent kernel processes all of them without dropping. Catches buffer-pool-sizing bugs: DOCA_ERROR_AGAIN from the device-side submit means the queue is full and the persistent kernel needs to drain faster, OR the buffer pool is undersized — per ## modify slot 5.

  3. TX smoke (if TX is in scope). Submit one TX packet from the persistent kernel via the GPU-visible TX handle; confirm it arrives at the peer. The fast-path TX submit from device code is independent of the RX path and can fail differently (different cap-query axis).

  4. Multi-GPU scale-out (if used). Re-run steps 1-3 on each doca_gpu independently — different GPUs in the same host can fail the dual capability check differently (e.g. an Ampere card supports GPUNetIO while a Turing card in the same chassis does not). Per CAPABILITIES.md ## Capabilities and modes the per-GPU rule, each card is its own configuration.

  5. Negative test. Intentionally point the persistent kernel at a CUDA device that should NOT support GPUNetIO (e.g. a pre-Ampere card) and confirm the dual capability discovery from ## configure step 3 reports the DOCA_ERROR_NOT_SUPPORTED cleanly — validates the agent's capability-discovery itself is correct.

Eval-loop overlay — why this is a loop, not a one-shot pass:

Iteration triggerWhat it looks likeWhat changes next iteration
DOCA_ERROR_NOT_SUPPORTED on a GPU we expected to workDOCA cap-query succeeded but the device failsThe CUDA-side axis was missed; re-run cudaGetDeviceProperties against the device ordinal and check nvidia_peermem is loaded
DOCA_ERROR_DRIVER on doca_gpu_createDOCA + CUDA versions are skewedRe-run the version chain per doca-version TASKS.md ## test (doca-version/TASKS.md#test); cross-check against the DOCA Compatibility Policy
Single-packet smoke passed; burst loop hangsThe persistent kernel is not draining the queue fast enough OR the buffer pool is too smallRaise the buffer pool size in ## modify slot 5; or restructure the persistent kernel to drain in larger batches
Persistent kernel runs but reports 0% GPU utilThe kernel is stuck on a queue drain or the doca-eth queue is not receivingConfirm the peer is generating traffic per ## run step 1; then re-run the dual capability discovery
doca_ctx_stop blocks on teardownThe persistent kernel is still running because the termination signal was never setWalk the host-side flag write that the kernel polls per ## modify slot 6

Loop termination: the loop ends when either (a) the persistent kernel processes packets at the user's intended rate with the expected accuracy — success — or (b) two consecutive iterations produce the same iteration-identity tuple (trigger-table row, doca-gpunetio / doca-common / CUDA version results, DOCA and CUDA capability results, parent doca-eth queue identity and counter outcome, persistent-kernel state, and packet / drain outcome). Matching evidence across both iterations requires escalation, never success; the cause is below GPUNetIO (CUDA driver, NIC firmware, network). Escalate to doca-debug TASKS.md ## debug (doca-debug/TASKS.md#debug) with the captured layer-1-through-5 evidence including BOTH the DOCA log and the nvidia-smi output.

debug

Goal: when a DOCA GPUNetIO call (or the persistent kernel) returns a DOCA_ERROR_* or does not make forward progress, narrow the cause to a specific layer and act on it.

The cross-library debug ladder lives in doca-debug TASKS.md ## debug (doca-debug/TASKS.md#debug). Walk through it in order — install → version → build → link → runtime → program → driver — before recommending GPUNetIO-specific fixes. This skill's overlay names the GPUNetIO-specific manifestation at layers 5 (runtime), 6 (program), and 7 (driver):

Layer 5 (runtime) — GPUNetIO overlay.

  • The persistent kernel never observing a completion is almost always one of three things: the underlying doca-eth queue is not actually receiving traffic; the GPU-visible handle is layered on a different queue than the one the peer is hitting; or the host-side PE is not being progressed. Confirm the env-side preconditions per ## configure step 1 before any code change.

  • DOCA_ERROR_AGAIN from device-side submit is always a queue-full / drain-rate problem. Do not recommend a retry loop in the kernel; recommend a faster drain step in the persistent kernel body.

  • A "persistent kernel hung; cannot stop the program" pattern is almost always a missing host-side termination flag per ## modify slot 6.

Layer 6 (program) — GPUNetIO overlay.

  • Lifecycle ordering: the GPU-visible handle must be destroyed BEFORE the underlying doca-eth queue is destroyed; the doca_gpu context must be destroyed BEFORE the CUDA context is unbound from the process. Out-of-order returns DOCA_ERROR_BAD_STATE per CAPABILITIES.md ## Safety policy.

  • Buffer registration: a CUDA-allocated buffer that was not registered with DOCA via doca_buf_arr_create_* before doca_ctx_start() returns DOCA_ERROR_BAD_STATE from the first device-side submit, not at create time. Walk the registration sequence in ## configure step 4.

  • Kernel-per-packet anti-pattern: if the user reports "throughput is much lower than expected" and the code launches a kernel per packet, that is the bug. Refactor to the persistent-kernel pattern per CAPABILITIES.md ## Capabilities and modes.

Layer 7 (driver) — GPUNetIO overlay.

  • DOCA_ERROR_DRIVER from doca_gpu_* is most often a CUDA driver layer reporting failure to DOCA. Capture nvidia-smi -q and dmesg | tail; cross-check the CUDA driver version against the DOCA Compatibility Policy.

  • nvidia_peermem not loaded silently degrades GPUDirect RDMA and surfaces as DOCA_ERROR_NOT_SUPPORTED at create time. Route to doca-setup TASKS.md ## debug (doca-setup/TASKS.md#debug) layer 5 (driver) for the kernel-module fix.

Once the layer is identified, route to the matching debug verb on the matching skill: install / build / link / driver to doca-setup ## debug (doca-setup/TASKS.md#debug); version to doca-version TASKS.md ## debug (doca-version/TASKS.md#debug); cross-cutting runtime to doca-debug ## debug (doca-debug/TASKS.md#debug); program-layer Core-context patterns to doca-programming-guide TASKS.md ## debug (doca-programming-guide/TASKS.md#debug).

5-phase universal debug-loop instantiation (GPUNetIO). Layer identification above is phase 1 of the universal debug-loop contract (doca-debug/CAPABILITIES.md#universal-debug-loop-contract). The agent MUST walk the remaining four phases on every GPUNetIO debug answer before declaring done:

  1. Layer identification — above (RX / lifecycle / driver).

  2. Triple capture (READ-ONLY). Capture (a) the saved configure-time doca_devinfo, parent doca_eth_rxq identity, doca_eth_rxq_cap_is_type_supported(...) result, and ethtool -S <netdev> RX counters, (b) DOCA log lines at DOCA_LOG_LEVEL=DEBUG for the offending submit / drain, and (c) GPU-side state via nvidia-smi -q + cuda-memcheck (or compute-sanitizer) on the persistent kernel. Capture ALL THREE before mutating; the triple is the rollback target.

  3. Single-variable mutation SMALLER than the original change. Examples: drop the kernel's per-iteration drain width by half (not refactor to per-packet); register one extra buffer (not the full pool); switch one queue to the doca-eth smoke sample (not the production topology). Larger mutations void the experiment.

  4. Re-capture and compare. Re-run the triple from phase 2; diff against the baseline. The compare diff IS the evidence, not the agent's prose interpretation.

  5. Exit with named green signal OR escalate. Green = the specific counter / log line / GPU state the bug was negating. Examples: ethtool -S rx_packets increments AND GPU buffer holds the bytes; no compute-sanitizer errors; stop-flag termination clean. If two consecutive iterations don't change anything, the cause is below GPUNetIO — escalate to doca-debug TASKS.md ## debug (doca-debug/TASKS.md#debug) with the captured triple.

rollback

GPUNetIO contexts are stateful (persistent kernel + GPU buffer registration + doca-eth queue) and the agent's failure mode is to leave half-registered GPU buffers behind after a botched configure → start sequence. The universal verification contract (doca-setup/CAPABILITIES.md#universal-verification-contract) step 1 (preconditions) requires "the rollback path is documented" on every change-recommending answer; this is the GPUNetIO instantiation.

Snapshot before mutate. Before any change-recommending GPUNetIO answer, capture the GPU-side allocation map (nvidia-smi -q -d MEMORY + cudaGetDeviceProperties), the doca-eth queue attachment map (the saved configure-time doca_devinfo, eth RXQ identity, and doca_eth_rxq_cap_is_type_supported(...) result), and the persistent-kernel stop-flag location. The triple IS the rollback target.

  1. Signal the persistent kernel to drain and stop FIRST. Flip the host-side termination flag from ## modify slot 6 before any context destroy. Before flipping it, record a fixed drain deadline. Poll cudaStreamQuery on the kernel's stream until it reports completion or that predeclared deadline expires; do not call cudaDeviceSynchronize for this drain. If the deadline expires, the kernel is hung — that is the deploy-loop bridge (doca-setup/CAPABILITIES.md#deploy-loop-bridge--step-5-not-green-is-the-debug-loop-trigger) trigger, not a rollback trigger; fire the debug-loop on the hung-kernel symptom. Fail closed: do not continue to steps 2-4 or call doca_buf_arr_destroy, doca_ctx_stop, doca_gpu_destroy, or cudaFree while kernel completion is unconfirmed. Preserve the rollback snapshot and escalate with the captured debug triple. Resume rollback only after cudaStreamQuery reports completion.

  2. Unregister GPU buffers in reverse-register order. doca_buf_arr_destroy on every array created with doca_buf_arr_create_*. Buffers MUST be unregistered before cudaFree; the reverse order is non-negotiable per CAPABILITIES.md ## Safety policy.

  3. Stop and destroy the GPUNetIO context. doca_ctx_stop on the doca_gpu context, then doca_gpu_destroy. The parent doca-eth RXQ remains valid and must not be torn down by this step.

  4. cudaFree the underlying GPU allocations. Only after the DOCA-side unregister landed clean. Skipping this step leaks GPU memory at process exit and surfaces as CUDA_ERROR_LAUNCH_FAILED on the next program run with the same NUMA-pinned GPU.

  5. Re-verify the doca-eth parent is intact. Re-run the eth RXQ smoke from doca-eth TASKS.md ## test (doca-eth/TASKS.md#test) to confirm the parent queue still receives packets at the pre-GPUNetIO rate. If not, the GPUNetIO rollback corrupted the parent — that is a bug to surface, not a retry trigger.

Verification-contract requirement. Document the rollback verb in the verification contract preconditions block. The step 1 line for a GPUNetIO add reads: "the rollback path is the five-step reversal in ## rollback; the agent has captured the GPU allocation map and persistent-kernel stop-flag location." Without that line, the contract is incomplete and the agent is NOT eligible to declare done.

The rollback is bounded — on the second non-green re-verify at step 5, the agent MUST surface the unresolved residual gap instead of recommending another GPUNetIO retry.

Deferred task verbs

The following verbs are out of scope for this skill but are commonly asked in the same conversations. Route them as follows so the agent does not invent guidance:

  • install. Installing DOCA, installing the CUDA toolkit, choosing matched versions, post-install verification, pkg-config wiring, loading nvidia_peermem — defer to doca-setup/SKILL.md and to the install-tree layout in doca-public-knowledge-map ## Layout of an installed DOCA package (doca-public-knowledge-map/SKILL.md#layout-of-an-installed-doca-package). This skill assumes DOCA + CUDA are already installed and matched.

  • deploy. Deploying GPUNetIO-using applications at scale (multi-GPU multi-NIC clusters, Kubernetes operator workflows for GPU + DPU workloads, multi-tenant GPU sharing for GPU-initiated networking) — out of scope for this skill. For single-host first-run testing, the right verb in this skill is ## run; do not invent a "deploy" workflow.

  • CUDA kernel design and tuning. Block / thread sizing, warp-level optimization, shared memory layout inside the persistent kernel — out of scope. Route to the upstream CUDA toolkit documentation via doca-public-knowledge-map/SKILL.md; this skill prescribes that the user uses the persistent-kernel pattern, not how to tune it.

  • DOCA Ethernet queue setup. Bringing up the underlying doca_eth_rxq / doca_eth_txq, RSS configuration, representor selection — GPUNetIO depends on it but does not redefine it. Route to doca-eth/SKILL.md.

Command appendix

Every command below is cross-cutting on DOCA GPUNetIO — it answers a recurring class of question that comes up in the verbs above. The agent should treat the class as load-bearing; the worked example is a single instance. Run-as user is the unprivileged user unless noted. Rows that need elevated privileges call that out explicitly.

Infra-aware preamble (every row below). Per the bundle's detect → prefer → fall back → report contract documented in doca-structured-tools-contract ## The agent behavior contract (doca-structured-tools-contract/SKILL.md#the-agent-behavior-contract), the agent should:

  1. Probe for the matching structured helper FIRST (doca-env --json for version + devices + libraries + drivers + hugepages in one shot; doca-capability-snapshot for per-device capability flags; version-matrix.json for "available since" lookups).

  2. If the probe succeeds, the structured tool's output is the authoritative answer and the agent SHOULD NOT also run the manual command in the row below. Report "using structured <tool>".

  3. If the probe fails, fall back to the manual command in the row. Report "falling back to manual chain".

  4. The schemas the structured tools emit are defined in doca-structured-tools-contract ## Schemas (doca-structured-tools-contract/SKILL.md#schemas); the version-handling semantics (four-way match, NGC, headers-win) are owned by doca-version/SKILL.md.

Command (worked example)Owning stepClass of question it answersWhat healthy output looks like
pkg-config --modversion doca-gpunetio + pkg-config --modversion doca-common## configure step 1; ## build DOCA-version gateDo the GPUNetIO and common package surfaces come from the same DOCA install?Two matching semver strings. Disagreement = partial install (route to doca-version TASKS.md ## debug (doca-version/TASKS.md#debug) layer 2); then compare the matched DOCA version with nvcc --version per the compatibility policy
pkg-config --cflags --libs doca-gpunetio## buildWhat include + link flags does the linker need?Trust whatever pkg-config --cflags --libs produces on this install. Do not hardcode either the -I include path or the -l<name> flag form — both can drift between DOCA install profiles and DOCA majors; the on-disk .so basenames use underscores, while the .pc package names use hyphens, and pkg-config is the only thing that resolves both correctly. Hand-crafted -l lines silently break when DOCA upgrades.
nvcc --version## configure step 1; ## build minimum-CUDA slotWhat is the installed CUDA toolkit version?A release string the agent compares against the DOCA Compatibility Policy linked from CAPABILITIES.md ## Version compatibility
nvidia-smi -L## configure step 1; ## test step 4Which CUDA devices are enumerable on this host?One row per GPU with device ordinal, name, and UUID. Empty = NVIDIA driver not loaded; route to doca-setup TASKS.md ## debug (doca-setup/TASKS.md#debug)
lsmod | grep nvidia_peermem## configure step 1; ## debug layer 7Is the nvidia_peermem module loaded for GPUDirect RDMA?One line showing the module loaded. Empty = sudo modprobe nvidia_peermem (env-side fix, not a code change)
ls /opt/mellanox/doca/samples/doca_gpunetio/## modify slot 1Which GPUNetIO samples ship in this install, and which is the closest starting point?A list of sample directories named after the RX / TX / persistent-kernel pattern they demonstrate
nvidia-smi -q -d UTILIZATION## run step 4; ## debug layer 5Is the persistent kernel actually busy on the GPU?Non-zero GPU util while the kernel runs. 0% = stuck on a queue drain or the doca-eth queue is not receiving
dmesg | tail -n 40 (sudo)## debug layer 7What did the kernel / driver log around the last GPUNetIO call?Empty or recent benign messages. Repeated mlx5 / nvidia errors → driver-layer bug; route to doca-setup ## debug (doca-setup/TASKS.md#debug)
DOCA_LOG_LEVEL=trace ./<binary>## run step 4What did the structured DOCA logger emit for the first failing call?A trace-level line on every lifecycle transition. Silence after the persistent kernel launches = host-side PE not progressed
cat /usr/local/cuda/version.txt## configure step 1; ## debug layer 2What does the CUDA install tree itself claim its version is?A version string matching nvcc --version. Disagreement = partial CUDA install; route to doca-setup TASKS.md ## debug (doca-setup/TASKS.md#debug)

For commands shared across libraries (pkg-config --modversion, doca_caps, cat /opt/mellanox/doca/applications/VERSION, DOCA_LOG_LEVEL) the cross-library overlay is in doca-debug TASKS.md ## Command appendix (doca-debug/TASKS.md#command-appendix); this table adds the GPUNetIO-specific rows on top.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

The author says: Requires DOCA SDK at /opt/mellanox/doca on Linux (Ubuntu 22.04/24.04 or RHEL/SLES) with a BlueField DPU or ConnectX NIC. Reads the local install via `pkg-config doca-gpunetio`. Requires an NVIDIA GPU with CUDA toolkit (matched to DOCA per the DOCA Compatibility Policy) and GPU memory registered via dmabuf (or the legacy nvidia-peermem fallback) for GPUDirect RDMA; some samples need an InfiniBand-capable RNIC. The validation steps require a live DOCA install.

Security

What our scanner noticed· Medium risk

  • Large base64-encoded blobs

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
NVIDIA
Publisher
NVIDIA (Official)
Source
NVIDIA/skills · skills/doca-gpunetio · commit fce3cca
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE-APACHE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by NVIDIA or NVIDIA.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download doca-gpunetio.zip