Skip to content

feat(fast_io): io_uring SEND_ZC network zero-copy primitive (#1832)#4301

Merged
oferchen merged 1 commit into
masterfrom
feat/iouring-send-zc-1832
May 17, 2026
Merged

feat(fast_io): io_uring SEND_ZC network zero-copy primitive (#1832)#4301
oferchen merged 1 commit into
masterfrom
feat/iouring-send-zc-1832

Conversation

@oferchen
Copy link
Copy Markdown
Owner

Summary

  • Adds crates/fast_io/src/io_uring/send_zc.rs exposing try_send_zc(ring, fd, buf, user_data) that submits an IORING_OP_SEND_ZC SQE and drains both the transfer CQE (IORING_CQE_F_MORE) and the notification CQE (IORING_CQE_F_NOTIF) before returning. Kernel support is probed via IORING_REGISTER_PROBE on first call and cached in a process-wide atomic; unsupported kernels surface io::ErrorKind::Unsupported.
  • Wires IoUringSocketWriter::submit_send to attempt SEND_ZC first when IoUringConfig::allow_send_zc() is true and the payload is at least 16 KiB (workload-B regression guard from docs/design/iouring-send-zc.md section 5), falling back to the existing IORING_OP_SEND batch path on Unsupported.
  • Mirrors the API in the non-Linux stub so cross-platform callers compile without cfg-gating; updates the design doc to reflect the landed primitive.

Test plan

  • cargo fmt --all
  • CI: fmt+clippy
  • CI: nextest (stable) - covers send_zc::tests::* on the Linux runners (classify-CQE state machine, empty-buffer rejection, 64 KiB loopback round-trip)
  • CI: Windows / macOS / Linux musl - stub path compiles

Adds `crates/fast_io/src/io_uring/send_zc.rs` exposing
`try_send_zc(ring, fd, buf, user_data)` that submits an
`IORING_OP_SEND_ZC` SQE, drains both the transfer CQE
(`IORING_CQE_F_MORE`) and the notification CQE (`IORING_CQE_F_NOTIF`),
and returns the byte count sent. Kernel support is probed via
`IORING_REGISTER_PROBE` on first call and cached in a process-wide
atomic; unsupported kernels surface `io::ErrorKind::Unsupported` so
callers can fall back transparently.

`IoUringSocketWriter::submit_send` now attempts SEND_ZC first when
`IoUringConfig::allow_send_zc()` is true and the payload is at least
16 KiB (per the workload-B regression guard in
`docs/design/iouring-send-zc.md` section 5), falling back to the
existing `IORING_OP_SEND` batch path on `Unsupported`. A matching
stub module on non-Linux returns `Unsupported` so cross-platform
callers compile without `cfg`-gating.

Unit tests cover the classify-CQE state machine, the empty-buffer
rejection, and a 64 KiB loopback round-trip that succeeds only once
the notification CQE has been observed.
@oferchen oferchen merged commit 513d16a into master May 17, 2026
11 of 21 checks passed
@github-actions github-actions Bot added the enhancement New feature or request label May 17, 2026
oferchen added a commit that referenced this pull request May 18, 2026
…4301)

Adds `crates/fast_io/src/io_uring/send_zc.rs` exposing
`try_send_zc(ring, fd, buf, user_data)` that submits an
`IORING_OP_SEND_ZC` SQE, drains both the transfer CQE
(`IORING_CQE_F_MORE`) and the notification CQE (`IORING_CQE_F_NOTIF`),
and returns the byte count sent. Kernel support is probed via
`IORING_REGISTER_PROBE` on first call and cached in a process-wide
atomic; unsupported kernels surface `io::ErrorKind::Unsupported` so
callers can fall back transparently.

`IoUringSocketWriter::submit_send` now attempts SEND_ZC first when
`IoUringConfig::allow_send_zc()` is true and the payload is at least
16 KiB (per the workload-B regression guard in
`docs/design/iouring-send-zc.md` section 5), falling back to the
existing `IORING_OP_SEND` batch path on `Unsupported`. A matching
stub module on non-Linux returns `Unsupported` so cross-platform
callers compile without `cfg`-gating.

Unit tests cover the classify-CQE state machine, the empty-buffer
rejection, and a 64 KiB loopback round-trip that succeeds only once
the notification CQE has been observed.
oferchen added a commit that referenced this pull request May 18, 2026
…4301)

Adds `crates/fast_io/src/io_uring/send_zc.rs` exposing
`try_send_zc(ring, fd, buf, user_data)` that submits an
`IORING_OP_SEND_ZC` SQE, drains both the transfer CQE
(`IORING_CQE_F_MORE`) and the notification CQE (`IORING_CQE_F_NOTIF`),
and returns the byte count sent. Kernel support is probed via
`IORING_REGISTER_PROBE` on first call and cached in a process-wide
atomic; unsupported kernels surface `io::ErrorKind::Unsupported` so
callers can fall back transparently.

`IoUringSocketWriter::submit_send` now attempts SEND_ZC first when
`IoUringConfig::allow_send_zc()` is true and the payload is at least
16 KiB (per the workload-B regression guard in
`docs/design/iouring-send-zc.md` section 5), falling back to the
existing `IORING_OP_SEND` batch path on `Unsupported`. A matching
stub module on non-Linux returns `Unsupported` so cross-platform
callers compile without `cfg`-gating.

Unit tests cover the classify-CQE state machine, the empty-buffer
rejection, and a 64 KiB loopback round-trip that succeeds only once
the notification CQE has been observed.
@oferchen oferchen deleted the feat/iouring-send-zc-1832 branch May 19, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant